tamarin-prover-0.8.0.0: data/examples/loops/Minimal_Typing_Example.spthy
theory Minimal_Typing_Example
begin
/*
Protocol: A minimal example to demonstrate the use of typing assertions
Modeler: Simon Meier
Date: July 2012
Status: working
Note that this is an artificial example to demonstrate the use of typing
assertions. It is explained in detail in my Ph.D. thesis.
*/
builtins: symmetric-encryption, hashing
// Shared keys that can be compromised.
rule Setup_Key:
[ Fr(~k) ] --> [ !Key(~k) ]
rule Reveal_Key:
[ !Key(k) ] --[ Rev(k) ]-> [ Out(k) ]
/* The protocol: there are shared keys that all honest processes have access
* to. The intruder can access them too by revealing them using the
* 'Reveal_Key' rule above. We use these keys to exchange a message consisting
* of a public part and a secret part. The initiator sends the message and the
* responder claims that the secret part is secret provided that the used key
* has not been revealed by the adversary.
*/
rule Initiator:
let msg = senc{~sec,~pub}k
in
[ !Key(k), Fr(~sec), Fr(~pub) ]
--[ Out_Initiator(msg)
, Public(~pub)
]->
[ Out( msg ) ]
rule Responder:
let msg = senc{sec,pub}key
in
[ !Key(key), In( msg )
]
--[ In_Responder(msg, pub)
, Secret(sec, key)
]->
[ Out( pub ) ]
/* This is our typing assertion: it ensures that we have enough constraints on
* the 'pub' variable in the 'Responder' rule to determine all possible
* messages that can be extracted from it using the deconstruction rules.
* You can see the effect of having too few constraint in the GUI under the
* 'untyped precomupted case distinctions' link. Several cases have
* superfluous decryption chains. Getting rid of them is the goal of the
* typing assertion.
*
* Note that typing assertions are invariants over the traces of the normal
* form dependency graphs of a protocol. We mark lemmas with the 'typing'
* attribute to ensure that they are proving using induction and that they are
* reused when precomputing case distinctions and proving non-typing lemmas.
*/
lemma typing_assertion [typing]:
/* For all messages received by the responder */
"(All m k #i. In_Responder(m, k) @ i ==>
/* they either came from the adversary and he therefore knows the
* contained 'k' variable before it was instantiated */
( (Ex #j. KU(k) @ j & j < i)
/* or there is an initiator that sent 'm'. */
| (Ex #j. Out_Initiator(m) @ j)
)
)
"
/* Note that in general typing assertions do not directly relate received
* messsages to sent messages, but received cryptographic components to sent
* cryptographic components. For this simple protocol, the two notions
* however coincide.
*/
/* The secret part of the message received by Responder is secret provided the
* key has not been compromised.
*/
lemma Responder_secrecy:
" /* For all traces, we have that */
All sec key #i #j.
/* if a responder claims the secrecy of a message 'sec' provided 'key'
* is not compromised */
Secret(sec, key) @ #i
/* and the adversary nevertheless deduced 'k' */
& K(sec) @ #j
/* then the adversary must have revealed 'key' */
==>
(Ex #r. Rev(key) @ r)
"
/* Sanity check: the public part is accessible to the adversary without
* performing a key reveal.
*/
lemma Public_part_public:
exists-trace
" /* No key reveal has been performed */
not (Ex k #i. Rev(k) @ i)
/* and the public part of a message is known to the adversary. */
& (Ex pub #i #j. Public(pub) @ i & K(pub) @ j )
"
end