free usb : channel.
(* Definitions for key signature and mac *)

type id.
type pkey.
type skey.
type stamp.

type side.
free left:side [private].
free right:side [private].

free counter1:channel [private].
free counter2:channel [private].
free lock:channel [private].
free st0:stamp.

fun pk(skey) :  pkey.

not attacker(lock).
not attacker(counter1).
not attacker(counter2).

nounif i:nat; mess(lock,i) [ignoreAFewTimes].
nounif i:nat; mess(counter1,i) [ignoreAFewTimes].
nounif i:nat; mess(counter2,i) [ignoreAFewTimes].

event Counter(channel,side,stamp,nat).

set inductionLemmas = true.

axiom i:nat,i1:nat,i2:nat,st:stamp,st1:stamp,st2:stamp,st3:stamp, st4:stamp, d:channel, s:side;
  event(Counter(d,s,st,i1)) && event(Counter(d,s,st,i2)) ==> (i1 = i2 && st <> st0) || st = st0;
  event(Counter(d,s,st1,i)) && event(Counter(d,s,st2,i)) ==> (st1 = st2 && st <> st0 && st2 <> st0) || st1 = st0 || st2 = st0;
  event(Counter(d,s,st,i)) ==> is_nat(i) [fullSat].

lemma l:nat,i:nat,j:nat,st:stamp,st1:stamp,st2:stamp,st3:stamp, d:channel;
  event(Counter(lock,left,st,l)) && event(Counter(counter1,left,st,i)) ==> ((i = 0 && st1 = st0) || (l = i && st1 <> st0));
  event(Counter(lock,left,st,i)) && event(Counter(counter1,left,st2,i)) ==> (st = st2 && st <> st0 )|| st2 = st0.

let T_auth2( ) =
    	   in(lock,l:nat);
	   new st[]:stamp;
	   event Counter(lock,choice[left,right],st,l+1);

	   in(counter1,i:nat);
	   event Counter(counter1,choice[left,right],choice[st,st0],choice[i+1,i]);
	   out(counter1,choice[i+1,i]);

           in(counter2,j:nat);
	   event Counter(counter2,choice[left,right],choice[st0,st],choice[j,j+1]);
	   out(counter2,choice[j,j+1]);

	   out(lock,l+1);

	   out(usb,choice[i,j]).



process
(! in (counter1, x:nat) ; out(counter1,x); 0 ) |
(! in (counter2, x:nat) ; out(counter2,x); 0 ) |
(! in (lock, x:nat) ; out(lock,x); 0 ) |

(
out(counter1, 0);
out(counter2, 0);
out(lock, 0);
  (
   !T_auth2( )
  )
)

(*
ski is the master key of yubikey_i
we associate the counteri to yubikey_i

Check whether two accounts (id1, id2) on the same yubikey sk1 with the same counter
is distinguishable from two accounts (id1, id2) on two different yubikeys (with different counters)
*)

(* EXPECTPV
RESULT event(Counter(lock[],left[],st_1,l_1)) && event(Counter(counter1[],left[],st_1,i_1)) ==> (i_1 = 0 && st1 = st0[]) || (l_1 = i_1 && st1 ≠ st0[]) cannot be proved.
RESULT event(Counter(lock[],left[],st_1,i_1)) && event(Counter(counter1[],left[],st2,i_1)) ==> (st_1 = st2 && st_1 ≠ st0[]) || st2 = st0[] cannot be proved.
0.124s (user 0.092s + system 0.032s), max rss 10256K
END *)
