
 param traceDisplay = long. 
(* param verboseClauses = short.*)

free ch.
free lk.
free lk1, lk2.
free cwk.

private fun handle/2.
private fun tpmproof/0.
private fun priv/1. 

private fun secret/0.

fun hmac/2.
fun pk/1. 
fun ok/0.
fun hash/2.
fun hmac320/2.
fun dec/2.
fun enc/2.
fun wrap/2.
fun unwrap/2.

equation dec(enc(x,y),y) = x.
equation unwrap(wrap(x,pk(y)),y) = x.


(* theory to deal with the Key table *)
private reduc getAuth(handle(pw,sk)) = pw.
reduc getPK(handle(pw,sk)) = pk(sk).
private reduc getSK(handle(pw,sk)) = sk.

 nounif attacker:handle(x,y). 


(* query attacker:secret. *)


(* Correspondance pour CreateWrapKey *)
(* query evinj:UserConsidersKeyCreated(x1,x2,x3,x4,x5) ==> evinj:TpmCreateKey(x1,x2,x3,x4,x5) | attacker:x1. *)
(* query evinj:TpmHasCreatedKey(x1,x2,x3,x4,x5) ==> evinj:UserRequestsKeyCreation(x1,x2,x3) | attacker:x1. *)


(* Correspondance pour LoadKey - ProVerif dit que ces deux proprietes sont vraies *)
 query ev:UserConsidersKeyLoading(x1,x2,x3) ==> ev:TPMLoadsKey(y1,x2,x3)| attacker:x2. 


(* query evinj:TPMHasLoadedKey(x1,x2,x3) ==> evinj:UserRequestsKeyLoading(x1,x2,x3) | attacker:x2. *)



(************* Command Wrap Key ***************************)


let TPM_CreateWrapKey =
        (* Reception of the key handle  kh *)
	in(ch,kh);
	(* Reception of the OSAP nonce odd *)
	in(ch,noOSAP);	
	(* Rolling nonce even and Nonce even OSAP generated by the TPM *)
	new NeOSAP; new Ne;
	out(ch, NeOSAP); out(ch,Ne);
	(* Reception of the rolling nonce odd, the hmac, the new autdata encrypted *)
        in(ch, (no,hm,encuauth));
	(* TPM retrieves the authdata, the private key and the public key associated to kh *)
	let  auth = getAuth(kh) in
	let sk = getSK(kh) in
	(* computation of the share secret *)
	let ss = hmac320(auth,(NeOSAP,noOSAP)) in
	(* Verification of the hmac *)
	if hm = hmac(ss, (cwk,pk(sk),encuauth,Ne,no)) then
	(* Creation of the new key and of the new rolling nonce *)
	(* new secretK; *) 
	new Ne'; 
	let uauth = dec(encuauth,hash(ss,Ne)) in
	new secretK;
	let wrp = wrap((secretK,uauth,tpmproof),pk(sk)) in
	let hmtpm = hmac(ss,(cwk, pk(sk),wrp, pk(secretK), Ne', no)) in
	out(ch,Ne');
	out(ch,pk(secretK));
	out(ch,wrp);
	event TpmCreateKey(auth,sk,uauth,pk(secretK),wrp);
	out(ch, hmtpm);	
	event TpmHasCreatedKey(auth,sk,uauth,pk(secretK),wrp).



let USER_CreateWrapKey =
        (* The entry in the Key table is chosen by the attacker *)
	in(ch, kh1);
	let  auth1 = getAuth(kh1) in
	let sk1 = getSK(kh1) in
	(* Generation of the OSAP odd nonce *)
	new  NoOSAP; out(ch,NoOSAP);
	(* Reception of the OSAP even nonce and the even rolling nonce *)
	in(ch,neOSAP); in(ch,ne);
	let ssuser= hmac320(auth1, (neOSAP,NoOSAP)) in
	(* Generation of the rolling odd nonce *)
	new No; out(ch,No);
	(* Generation of the two new auth data *)
	new Uauth; 
	let encUauth = enc(Uauth,hash(ssuser,ne)) in 
	let hm = hmac(ssuser, (cwk, pk(sk1),encUauth, ne, No)) in 
	event UserRequestsKeyCreation(auth1,sk1,Uauth);	
	out(ch,(encUauth,hm));
	(* Reception of the even nonce, the public key, the wrap and the associated hmac *)
	in(ch, (ne',ypk,ywrp, htpm));
        if htpm = hmac(ssuser,(cwk,pk(sk1),ywrp,ypk,ne',No)) then
        event UserConsidersKeyCreated(auth1,sk1,Uauth,ypk,ywrp).
	



(************* Command Load Key ***************************)



let TPM_LoadKey =
	(* Reception of the key handle kh, the nonce odd no, the wrap wrp, the public key and the hmac hm *)
        in(ch, (kh1, no, xpk, xwrp, hm));
	(* Nonces even generated by the TPM *)
	new Ne;	out(ch, Ne);
	(* TPM retrieves the authdata, the private key and the public key associated to hi *)
	let  auth1 = getAuth(kh1) in
	let sk1 = getSK(kh1) in
	(* Verification of the hmac *)
	if hm = hmac(auth1, (lk1,pk(sk1), xpk,xwrp,Ne,no)) then
	(* Creation of a new key handle *)
	(* Creation of a new rolling nonce *)
	new Ne'; out(ch,Ne');
	let (xsk,xuauth, xtpmproof) = unwrap(xwrp, sk1) in
	(* Doit-on mettre ce test *)
	(* if xsk = hsk(xuauth) then *)
	if xtpmproof = tpmproof then
	let hmtpm = hmac(auth1,(lk2,pk(sk1),Ne',no)) in
	event TPMLoadsKey(xwrp,auth1,sk1);
	out(ch,handle(xuauth,xsk)); 
	out(ch, hmtpm);
		out(ch,secret);
	event TPMHasLoadedKey(xwrp,auth1,sk1).
 

let USER_LoadKey =
        (* The entry in the Key table is chosen by the attacker *)
	in(ch, h1); 
	(* The public key and the wrap are also chosen by the attacker *)
	in(ch,pubk); in(ch,wrp);
	(* Reception of the even nonces *)
	in(ch, ne1);	new No1; 
	(* Generation of nonces *) 
	(* The user retrieves the authdata and the secret keys associated to the handles *)
	let  auth1=  getAuth(h1) in
	let sk1 = getSK(h1) in
      	(* Construction of the hmac *)
	let hmac1 = hmac(auth1, (lk1,pk(sk1),pubk,wrp, ne1, No1)) in
	event UserRequestsKeyLoading(wrp,auth1,sk1);
	out(ch, (No1, pubk, wrp, hmac1));
	in(ch, (ne1', hm1));
        if hm1 = hmac(auth1,(lk2,pk(sk1),ne1',No1)) then
	 event UserConsidersKeyLoading(wrp,auth1,sk1).
	

process
	(* Alice *)
	new aliceAuth; new aliceKeySK;
	let aliceKeyPK = pk(aliceKeySK) in out(ch,aliceKeyPK);
     	out(ch, handle(aliceAuth,aliceKeySK));  
	(* Alice *)
	new aliceAuth2; new aliceKeySK2;
	let aliceKeyPK2 = pk(aliceKeySK2) in out(ch,aliceKeyPK2);
  	out(ch, handle(aliceAuth2,aliceKeySK2)); 
	(* Alice *)
	new aliceKeySK';
	let aliceKeyPK' = pk(aliceKeySK') in out(ch,aliceKeyPK');
     	out(ch, handle(aliceAuth,aliceKeySK'));  
	(* Alice *)
	new aliceKeySK2';
	let aliceKeyPK2' = pk(aliceKeySK2') in out(ch,aliceKeyPK2');
  	out(ch, handle(aliceAuth2,aliceKeySK2')); 
	(* Charlie *)
	new charlieAuth; out(ch,charlieAuth); new charlieKeySK;
	let charlieKeyPK = pk(charlieKeySK) in out(ch, charlieKeyPK);
	out(ch, handle(charlieAuth,charlieKeySK)); 
	( 
	!TPM_LoadKey | !USER_LoadKey | !TPM_CreateWrapKey |!USER_CreateWrapKey) 

(* EXPECTPV
RESULT ev:UserConsidersKeyLoading(x1,x2,x3) ==> ev:TPMLoadsKey(y1,x2,x3) | attacker:x2 cannot be proved.
0.284s (user 0.264s + system 0.020s), max rss 20488K
END *)
