hash h
hash h1
hash h2
hash h3
abstract ok : message
abstract error : message
abstract TSinit : message
abstract TSorderOk : message
abstract TSorder : message * message -> message
abstract TSnext : message -> message
name k : message
name key1 : index -> message
name key2 : index -> message
name key3 : index -> message
name pin : index -> message
name idinit : index -> message
mutable kT(i:index) : message = <idinit(i),TSinit>
mutable kR(ii:index) : message = idinit(ii)
mutable TS : message = TSinit
channel cT
channel cR
(* i = tag's identity, j = tag's session for identity i *)
process tag(i:index,j:index) =
in(cR, x1);
if fst(x1) = h(snd(x1),k) && TSorder(snd(kT(i)),snd(x1)) = TSorderOk then
(out(cT, h1(fst(kT(i)),key1(i)));
in(cR, x3);
if x3 = h2(<fst(kT(i)),pin(i)>,key2(i)) then
(kT(i) := <h3(<<fst(kT(i)),pin(i)>,snd(x1)>,key3(i)), snd(x1)>;
out(cT, ok))
else
out(cT, error))
else
out(cT, error)
(* jj = generic reader's session *)
process reader(jj:index) =
TS := TSnext(TS);
out(cR, <h(TS,k),TS>);
in(cT, x2);
try find ii such that x2 = h1(kR(ii), key1(ii)) in
let m = h2(<kR(ii),pin(ii)>,key2(ii)) in
kR(ii) := h3(<<kR(ii),pin(ii)>,TS>,key3(ii));
out(cR, m)
else
out(cR, error)
system ((!_jj R: reader(jj)) | (!_i !_j T: tag(i,j))).
Typed-check process:
null
Added action dependencies lemmas:
System after processing:
null
System Empty registered with actions (init).
[warning>Loaded "Prelude.sp".
<]global axiom namelength_k {'P:system} @system:(set:'P; equiv:None) :
[len k = namelength_message]
global axiom namelength_key1 {'P:system} @system:(set:'P; equiv:None) :
[forall (i:index), len (key1 i) = namelength_message]
global axiom namelength_key2 {'P:system} @system:(set:'P; equiv:None) :
[forall (i:index), len (key2 i) = namelength_message]
global axiom namelength_key3 {'P:system} @system:(set:'P; equiv:None) :
[forall (i:index), len (key3 i) = namelength_message]
global axiom namelength_pin {'P:system} @system:(set:'P; equiv:None) :
[forall (i:index), len (pin i) = namelength_message]
global axiom namelength_idinit {'P:system} @system:(set:'P; equiv:None) :
[forall (i:index), len (idinit i) = namelength_message]
process tag (i,j:index) =
in(cR,x1);
if fst x1 = h (snd x1, k) && TSorder (snd (kT i@τ), snd x1) = TSorderOk then
out(cT,h1 (fst (kT i@τ), key1 i));
in(cR,x3);
if x3 = h2 (<fst (kT i@τ),pin i>, key2 i) then
kT(i) := <h3 (<<fst (kT i@τ),pin i>,snd x1>, key3 i),snd x1>;
out(cT,ok);
null
else
out(cT,error); null
else
out(cT,error); null
process reader (jj:index) =
TS := TSnext (TS@τ);
out(cR,<h (TS@τ, k),TS@τ>);
in(cT,x2);
find (ii) such that x2 = h1 (kR ii@τ, key1 ii) in
let m : message = h2 (<kR ii@τ,pin ii>, key2 ii) in
kR(ii) := h3 (<<kR ii@τ,pin ii>,TS@τ>, key3 ii);
out(cR,m);
null
else
out(cR,error); null
Typed-check process:
( !_jj( R: reader jj) ) | !_i( !_j( T: tag i j))
Added action dependencies lemmas:
axiom mutex_T3_T2 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), not happens(T3(i, j)) || not happens(T2(i, j))
axiom mutex_T3_T1 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), not happens(T3(i, j)) || not happens(T1(i, j))
axiom mutex_T3_T {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), not happens(T3(i, j)) || not happens(T(i, j))
axiom mutex_T2_T3 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), not happens(T2(i, j)) || not happens(T3(i, j))
axiom mutex_T2_T1 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), not happens(T2(i, j)) || not happens(T1(i, j))
axiom mutex_T1_T3 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), not happens(T1(i, j)) || not happens(T3(i, j))
axiom mutex_T1_T2 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), not happens(T1(i, j)) || not happens(T2(i, j))
axiom mutex_T_T3 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), not happens(T(i, j)) || not happens(T3(i, j))
axiom depends_T_T2 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), happens(T2(i, j)) => T(i, j) < T2(i, j)
axiom depends_T_T1 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), happens(T1(i, j)) => T(i, j) < T1(i, j)
axiom mutex_R2_R1 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (jj,ii:index), not happens(R2(jj)) || not happens(R1(jj, ii))
axiom mutex_R1_R2 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (jj,ii:index), not happens(R1(jj, ii)) || not happens(R2(jj))
axiom depends_R_R2 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (jj:index), happens(R2(jj)) => R(jj) < R2(jj)
axiom depends_R_R1 {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (jj,ii:index), happens(R1(jj, ii)) => R(jj) < R1(jj, ii)
axiom depends_init_T3 {'P:system[like default]} @system:(set:'P; equiv:None)
: forall (i,j:index), happens(T3(i, j)) => init < T3(i, j)
axiom depends_init_T2 {'P:system[like default]} @system:(set:'P; equiv:None)
: forall (i,j:index), happens(T2(i, j)) => init < T2(i, j)
axiom depends_init_T1 {'P:system[like default]} @system:(set:'P; equiv:None)
: forall (i,j:index), happens(T1(i, j)) => init < T1(i, j)
axiom depends_init_T {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (i,j:index), happens(T(i, j)) => init < T(i, j)
axiom depends_init_R2 {'P:system[like default]} @system:(set:'P; equiv:None)
: forall (jj:index), happens(R2(jj)) => init < R2(jj)
axiom depends_init_R1 {'P:system[like default]} @system:(set:'P; equiv:None)
: forall (jj,ii:index), happens(R1(jj, ii)) => init < R1(jj, ii)
axiom depends_init_R {'P:system[like default]} @system:(set:'P; equiv:None) :
forall (jj:index), happens(R(jj)) => init < R(jj)
System after processing:
( !_jj(
TS := TSnext (TS@τ);
R: out(cR,<h (TS@τ, k),TS@τ>);
in(cT,x2);
find (ii) such that x2 = h1 (kR ii@τ, key1 ii) in
let m : message = h2 (<kR ii@τ,pin ii>, key2 ii) in
kR(ii) := h3 (<<kR ii@τ,pin ii>,TS@τ>, key3 ii);
R1: out(cR,m jj ii@τ);
null
else
R2: out(cR,error); null) ) |
!_i(
!_j(
in(cR,x1);
if fst x1 = h (snd x1, k) &&
TSorder (snd (kT i@τ), snd x1) = TSorderOk then
T: out(cT,h1 (fst (kT i@τ), key1 i));
in(cR,x3);
if x3 = h2 (<fst (kT i@τ),pin i>, key2 i) then
kT(i) :=
<h3 (<<fst (kT i@τ),pin i>,snd (input@T(i, j))>, key3 i),
snd (input@T(i, j))>;
T1: out(cT,ok);
null
else
T2: out(cT,error); null
else
T3: out(cT,error); null))
System Empty registered with actions (init).
System default registered with actions (init,R,R1,R2,T,T1,T2,T3).
SLK06
T. van Deursen and S. Radomirović, ‘Attacks on RFID Protocols’,
Cryptology ePrint Archive, vol. 2008, no. 310, pp. 1–56, Aug. 2009.
The protocol assumes that the reader and tag share the secrets k, ID,
and PIN. While ID and PIN are unique to each tag, k is equal for all
tags the reader is allowed to authenticate. The tag further stores the
timestamp TSlast of the last successful mutual authentication
initialized to 0 at the factory.
R -> T : <h(k,TS),TS> T -> R : h(ID) if TS > TSlast ID
:= h(ID,PIN,TS) TSlast := TS R -> T : h(ID,PIN) ID’ :=
h(ID,PIN,TS)
COMMENTS - In this model we use 3 different keyed hash functions,
instead of a single (not keyed) hash function as in the
specification.
SECURITY PROPERTIES - authentication (reader and tag)
******************************************************************************