set allowDiffPatterns = true.

(********   This file has been automatically generated using the tool UKano. It encodes the frame opacity condition. ********)

(******************************************************)
(*                                                    *)
(*               BAC+PA+AA                            *)
(*                                                    *)
(******************************************************)

(* ==THEORY== *)

(* public communication channel *)
free c : channel.
free ct : channel.
free cr : channel.

(* constant values *)
free hole : bitstring.
free error_mac : bitstring.
free init : bitstring.
free read : bitstring.
free ok : bitstring.

 (* Encryption (with mac inside) *)
 (* for better readability, we compact encryption+mac into the following
    construction. We modeled this using pairs of encryption+mac in BAC sub-foler. *)
fun enc(bitstring, bitstring) : bitstring.
  reduc forall xm:bitstring, xk:bitstring;
        dec(enc(xm, xk), xk) = xm.
		       (* we check mac using idTest*)
letfun idEnc(m:bitstring, k:bitstring) = enc(dec(m, k), k).

 (* Signature *)
fun spk(bitstring) : bitstring.
fun sign (bitstring, bitstring) : bitstring.
reduc forall m: bitstring , k:bitstring ;
  getmess(sign(m, k)) = m.
reduc forall m: bitstring , k:bitstring ;
  checksign(sign(m, k), spk(k)) = m.

(* generate new bitstring from seed from two bitstrings *)
fun hashKey(bitstring, bitstring) : bitstring.


(*  *)


(* == PROTOCOL WITH IDEALISATION == *)
let SYSTEM =
new skP : bitstring;
( !
  new idDGI : bitstring;
  new k_48 : bitstring;
     !
      ((
        new nt: bitstring;
        out(ct, nt);
        in(ct, choice[x1: bitstring,x1id: bitstring]);
        if (enc(dec(x1,k_48),k_48) = x1) then
        (
            let ((xnr: bitstring,=nt,xkr: bitstring)) = dec(x1,k_48) in
            (
                new kt: bitstring;
                new hole__xnr_I_0: bitstring;
                new hole__k_48_I_1: bitstring;
                out(ct, choice[enc((nt,xnr,kt),k_48),enc((nt,hole__xnr_I_0,kt),hole__k_48_I_1)]);
                in(ct, choice[x2: bitstring,x2id: bitstring]);
                let ((=init,xrandR: bitstring)) = dec(x2,hashKey(kt,xkr)) in
                new randT: bitstring;
                new hole__xrandR_I_2: bitstring;
                new hole__skP_I_3: bitstring;
                new hole__xkr_I_4: bitstring;
                out(ct, choice[enc(sign((randT,xrandR),skP),hashKey(kt,xkr)),enc(sign((randT,hole__xrandR_I_2),hole__skP_I_3),hashKey(kt,hole__xkr_I_4))]);
                in(ct, choice[x3: bitstring,x3id: bitstring]);
                if (dec(x3,hashKey(kt,xkr)) = read) then
                new hole__idDGI_I_5: bitstring;
                out(ct, choice[enc((idDGI,sign(idDGI,skP)),hashKey(kt,xkr)),enc((hole__idDGI_I_5,sign(hole__idDGI_I_5,hole__skP_I_3)),hashKey(kt,hole__xkr_I_4))])
            )
            else
                out(ct, error_mac)
        )
        else
            out(ct, error_mac)
      )|(
        in(cr, choice[y1: bitstring,y1id: bitstring]);
        new nr: bitstring;
        new kr: bitstring;
        new hole__k_48_R_6: bitstring;
        out(cr, choice[enc((nr,y1,kr),k_48),enc((nr,y1id,kr),hole__k_48_R_6)]);
        in(cr, choice[y2: bitstring,y2id: bitstring]);
        let ((=y1,=nr,ykt: bitstring)) = dec(y2,k_48) in
        new randR: bitstring;
        new hole__ykt_R_7: bitstring;
        out(cr, choice[enc((init,randR),hashKey(ykt,kr)),enc((init,randR),hashKey(hole__ykt_R_7,kr))]);
        in(cr, choice[y3: bitstring,y3id: bitstring]);
        let (m_49: bitstring) = dec(y3,hashKey(ykt,kr)) in
        if (checksign(m_49,spk(skP)) = getmess(m_49)) then
        out(cr, choice[enc(read,hashKey(ykt,kr)),enc(read,hashKey(hole__ykt_R_7,kr))]);
        in(cr, choice[y4: bitstring,y4id: bitstring]);
        let ((ydgi: bitstring,ysign: bitstring)) = dec(y4,hashKey(ykt,kr)) in
        if (checksign(ysign,spk(skP)) = ydgi) then
        out(cr, ok)
      ))
)
 | (!
  new idDGI : bitstring;
  new k_48 : bitstring;
  out(c, idDGI);
     !
      ((
        new nt: bitstring;
        out(ct, nt);
        in(ct, choice[x1: bitstring,x1id: bitstring]);
        if (enc(dec(x1,k_48),k_48) = x1) then
        (
            let ((xnr: bitstring,=nt,xkr: bitstring)) = dec(x1,k_48) in
            (
                new kt: bitstring;
                new hole__xnr_I_0: bitstring;
                new hole__k_48_I_1: bitstring;
                out(ct, choice[enc((nt,xnr,kt),k_48),enc((nt,hole__xnr_I_0,kt),hole__k_48_I_1)]);
                in(ct, choice[x2: bitstring,x2id: bitstring]);
                let ((=init,xrandR: bitstring)) = dec(x2,hashKey(kt,xkr)) in
                new randT: bitstring;
                new hole__xrandR_I_2: bitstring;
                new hole__skP_I_3: bitstring;
                new hole__xkr_I_4: bitstring;
                out(ct, choice[enc(sign((randT,xrandR),skP),hashKey(kt,xkr)),enc(sign((randT,hole__xrandR_I_2),hole__skP_I_3),hashKey(kt,hole__xkr_I_4))]);
                in(ct, choice[x3: bitstring,x3id: bitstring]);
                if (dec(x3,hashKey(kt,xkr)) = read) then
                new hole__idDGI_I_5: bitstring;
                out(ct, choice[enc((idDGI,sign(idDGI,skP)),hashKey(kt,xkr)),enc((hole__idDGI_I_5,sign(hole__idDGI_I_5,hole__skP_I_3)),hashKey(kt,hole__xkr_I_4))])
            )
            else
                out(ct, error_mac)
        )
        else
            out(ct, error_mac)
      )|(
        in(cr, choice[y1: bitstring,y1id: bitstring]);
        new nr: bitstring;
        new kr: bitstring;
        new hole__k_48_R_6: bitstring;
        out(cr, choice[enc((nr,y1,kr),k_48),enc((nr,y1id,kr),hole__k_48_R_6)]);
        in(cr, choice[y2: bitstring,y2id: bitstring]);
        let ((=y1,=nr,ykt: bitstring)) = dec(y2,k_48) in
        new randR: bitstring;
        new hole__ykt_R_7: bitstring;
        out(cr, choice[enc((init,randR),hashKey(ykt,kr)),enc((init,randR),hashKey(hole__ykt_R_7,kr))]);
        in(cr, choice[y3: bitstring,y3id: bitstring]);
        let (m_49: bitstring) = dec(y3,hashKey(ykt,kr)) in
        if (checksign(m_49,spk(skP)) = getmess(m_49)) then
        out(cr, choice[enc(read,hashKey(ykt,kr)),enc(read,hashKey(hole__ykt_R_7,kr))]);
        in(cr, choice[y4: bitstring,y4id: bitstring]);
        let ((ydgi: bitstring,ysign: bitstring)) = dec(y4,hashKey(ykt,kr)) in
        if (checksign(ysign,spk(skP)) = ydgi) then
        out(cr, ok)
      ))
)
.
process SYSTEM

(* EXPECTPV
RESULT Diff-equivalence is true.
1.500s (user 1.456s + system 0.044s), max rss 205712K
END *)
