(************************************************************************
 *                                                                      *
 *       Kerberos 5 protocol                                            *
 *                                                                      *
 *       Joe-Kai Tsay, Bruno Blanchet, Aaron D. Jaggard, Andre Scedrov  *
 *                                                                      *
 *       Copyright (C) University of Pennsylvania, ENS, CNRS,           *
 *       Rutgers University, 2007-2008                                  *
 *                                                                      *
 ************************************************************************)

(*

    Copyright University of Pennsylvania, ENS, CNRS, Rutgers University
    authors of this file:   Joe-Kai Tsay, jetsay@math.upenn.edu,
                Bruno Blanchet, Bruno.Blanchet@ens.fr,
                Aaron D. Jaggard, adj@dimacs.rutgers.edu,
                Andre Scedrov, scedrov@math.upenn.edu
    
    
This file contains a model of the Kerberos 5 protocol, for use with the
cryptographic protocol verifier CryptoVerif. It is a companion to
the AsiaCCS'08 paper "Computationally Sound Mechanized Proofs for
Basic and Public-key Kerberos", by B. Blanchet, A. D. Jaggard, A. Scedrov,
and J.-K. Tsay.

This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software.  You can use, 
modify and/ or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info". 

As a counterpart to the access to the source code and  rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty  and the software's author,  the holder of the
economic rights,  and the successive licensors  have only  limited
liability. 

In this respect, the user's attention is drawn to the risks associated
with loading,  using,  modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean  that it is complicated to manipulate,  and  that  also
therefore means  that it is reserved for developers  and  experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or 
data to be ensured and,  more generally, to use and operate it in the 
same conditions as regards security. 

Anything other than deleting this file means that you have knowledge
of the CeCILL license and that you accept its terms.

*)



(* basic Kerberos 5, first round only (AS_exchange), 
consider authentication and  key secrecy properties *)

param NC, NC2, NC3, NK, NT, NS, NCK, NTK, NSK.

type nonce [large,fixed].
type kas [bounded].
type client [bounded].
type tgs [bounded].
type server [bounded].
type key [fixed].
type maxenc [bounded].
type timest [fixed].							

(* Message construction functions *)
fun concat1(key, nonce, timest, tgs):maxenc [data]. 		
fun concat2(key, timest, client):maxenc [data].  		
fun concat3(key, nonce, timest, server):maxenc [data].       	
fun pad(client, timest):maxenc [data].
fun padts(timest): maxenc [data].

equation forall y:key, x:timest, z:client, t2:key, y2:nonce, x2:timest, z2:tgs;		concat2(y,x,z) <> concat1(t2,y2,x2,z2).
equation forall t:key, y:nonce, x:timest, z:server, t2:key, y2:nonce, x2:timest, z2:tgs; concat3(t,y,x,z) <> concat1(t2,y2,x2,z2).
equation forall z:client, t:timest, t2:key, y2:nonce, x2:timest, z2:tgs;  	   	pad(z,t) <> concat1(t2,y2,x2,z2).
equation forall t:timest, t2:key, y2:nonce, x2:timest, z2:tgs;   		   	padts(t) <> concat1(t2,y2,x2,z2).
equation forall y:key, x:timest, z:client, t2: key, y2:nonce, x2:timest, z2:server; 	concat2(y,x,z) <> concat3(t2,y2,x2,z2).
equation forall y:key, x:timest, z:client, t2:timest, z2:client;    		   	concat2(y,x,z) <> pad(z2,t2). 
equation forall y:key, x:timest, z:client, t2:timest;    			   	concat2(y,x,z) <> padts(t2). 
equation forall t:key, y:nonce, x:timest, z:server, t2:timest, z2:client;  	   	concat3(t,y,x,z) <> pad(z2,t2).
equation forall t:key, y:nonce, x:timest, z:server, t2:timest;  			   	concat3(t,y,x,z) <> padts( t2).
equation forall t:timest, z:client, t2:timest;  					   	pad(z,t)<> padts(t2).

(* Shared-key encryption (IND-CPA and INT-CTXT Stream cipher) *)

proba Penc.
proba Pencctxt.

expand IND_CPA_INT_CTXT_sym_enc(key, maxenc, bitstring, enc, dec, injbot, Z, Penc, Pencctxt).

(* The function Z returns for each bitstring, a bitstring of the same length, consisting only of zeroes. *)
const  Zconcat1:maxenc.
const  Zconcat2:maxenc.
const  Zconcat3: maxenc.
const  Zpad:maxenc.
const  Zpadts: maxenc.
equation forall y:nonce, x:timest, z:tgs, t:key;
	Z(concat1(t,y,x,z)) = Zconcat1.
equation forall y:key, x:timest, z:client; 
	Z(concat2(y,x,z)) = Zconcat2.
equation forall  y:nonce, x:timest, z:server, t:key;
	Z(concat3(t,y,x,z)) = Zconcat3.
equation forall z:client, t:timest;
        Z(pad(z,t)) = Zpad.
equation forall t: timest;
        Z(padts(t)) = Zpadts.
					    
(* Channel declarations *)

channel c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19,c20, c21, c22, c23, c24, c25, start, finish, cC, cT.

(* Host names for honest hosts *)

const C : client.
const K : kas.
const T : tgs.
const S : server.

(* Key tables *)

table Ckey(client, key). 
table Tkey(tgs, key). 

(* Final accept messages *)						

fun acceptC(kas,tgs):bitstring.
fun acceptK(client):bitstring.

(* Authentication Queries *)

event fullKC(client, tgs, nonce, key, bitstring, bitstring).
event fullCK(kas, tgs, nonce, key, bitstring, bitstring).		

query x:bitstring, y:bitstring, z:bitstring, N:nonce, k:key;
       inj-event(fullCK(K,T,N,k,x,y)) ==> inj-event(fullKC(C,T,N,k,z,y)) public_vars keyAK.

query x:bitstring, y:bitstring, z:bitstring, N:nonce, k:key, k':key;	
      event(fullCK(K,T,N,k,x,y)) && event(fullKC(C,T,N,k',x,y)) ==> k = k' public_vars keyAK.

(* Theorem 6: Secrecy of the key AK *)

query secret keyAK. 


(* Code for the client C *)

let processC(Kc: key) = 
	in(c1, hostT:tgs);				(* choose TGS hostT *) 				 
	new n1:nonce;
	out(c2, (C, hostT, n1));
	in(c3, (=C, m:bitstring, m2:bitstring));		(* m = Ticket Granting Ticket *)
        let injbot(concat1(AK, =n1, tk, =hostT)) = dec(m2, Kc) in 
	event fullCK(K, hostT, n1, AK, m, m2);
	out(c18, acceptC(K, hostT));
	(* OK *)
	in(finish, ());
	if hostT = T then
	(
	let keyAK:key = AK		
	)
	else out(cC, AK).
	

(* Code for registering the keys *)

let processCKEY(Kc: key) =
    in(c13, (Khost:client, Kkey:key)); 
    if Khost = C then insert Ckey(C,Kc) else       (* The key for the client C is Kc; for other clients, the key is chosen by the adversary *)
    insert Ckey(Khost,Kkey).

let processTKEY(Kt: key) =
    in(c21, (Lhost:tgs, Lkey:key)); 
    if Lhost = T then insert Tkey(T,Kt) else     (* The key for the TGS T is Kt; for other TGSs, the key is chosen by the adversary *)
    insert Tkey(Lhost,Lkey).

(* Code for the Kerberos Authentication Server (KAS) K *)

let processK = 
	in(c14, (hostY:client, hostW:tgs, n:nonce));
    	get Ckey(=hostY, kY) in
    	get Tkey(=hostW, kW) in
	new AK:key;
	new tk:timest;
	let e3 = enc(concat2(AK, tk, hostY), kW) in			(* e3 = Ticket Granting Ticket (TGT) *)
	let e4 = enc(concat1(AK, n, tk, hostW), kY) in
	event fullKC(hostY, hostW, n, AK, e3, e4);
	out(c15, (hostY, e3, e4)).

(* Main process, which generates long-term keys and runs the various processes *)

process
	in(start, ());
	new Kc: key;	(* Kc = enc key between client C and KAS K *)
	new Kt: key;	(* Kt = enc key between TGS T and KAS K *)
	out(c25, ());
	((! iC <= NC processC(Kc)) | 
	 (! iK <= NK processK) |
	 (! iCK <= NCK processCKEY(Kc))|
	 (! iTK <= NTK processTKEY(Kt)))


(* EXPECTED
All queries proved.
0.212s (user 0.196s + system 0.016s), max rss 47824K
END *)

(* EXPECTPV
RESULT inj-event(fullCK(K,T,N,k,x,y)) ==> inj-event(fullKC(C,T,N,k,z,y)) public_vars keyAK is true.
RESULT event(fullCK(K,T,N,k,x,y)) && event(fullKC(C,T,N,k',x,y)) ==> k = k' public_vars keyAK is true.
RESULT secret keyAK is true.
0.076s (user 0.072s + system 0.004s), max rss 11364K
END *)
