/******************************************************************************* TITLE AUTHORS Attack against the group key handshake, when the authenticator immediately installs the GTK after sending a Group Message 1 to all clients. Notation: pmk = Pairwise Master Key ptk = Pairwise Transient Key, composed of: kck = Key Confirmation Key kek = Key Encryption Key tk = Temporal Key gtk = Group Transient Key A_ = Events only in authenticator process S_ = Events only in supplicant process *******************************************************************************/ theory Krack_fig7_015 begin builtins: symmetric-encryption, multiset functions: true/0, CalcPTK/1, mic/2, kck/1, kek/1, tk/1, verifyMic/3 equations: verifyMic(mic(m,k), m, k) = true let Supplicant = new ~S_id; out(~S_id); !( // Initial 4-way handshake new ~tid; in(A_id); let pat_msg1_contents = <'Header1', r, ANonce> in in(pat_msg1_contents); event Receive(A_id, ~S_id, 'Message1', r, pat_msg1_contents); new ~SNonce; let tptk = CalcPTK(<~pmk, ANonce, ~SNonce, A_id, ~S_id>) in event S_ComputesPTK(~tid, tptk); let msg2_contents = <'Header2', r, ~SNonce> in event Send(~S_id, A_id, 'Message2', r, msg2_contents); out(); let msg3_contents = <'Header3', r+'1', ANonce, senc(gtk, kek(tptk))> in in(); event Receive(A_id, ~S_id, 'Message3', r+'1', msg3_contents); let ptk = tptk in event Running(~S_id, A_id, <~SNonce, ANonce, r+'1', ptk, gtk>); let msg4_contents = <'Header4', r+'1'> in event Send(~S_id, A_id, 'Message4', r+'1', msg4_contents); out(); event S_InstallsPtk(~S_id, ptk); // MLME-SETKEYS.request event S_InstallsGtk(~S_id, gtk); // MLME-SETKEYS.request // Group rekey !( let group_msg1_contents = <'GrkHeader1', r2, senc(gtk2, kek(ptk))> in let m = in in(senc(m, tk(ptk))); event Receive(A_id, ~S_id, 'Message1', r2, group_msg1_contents); event ReceivesCiphertext(~S_id, m, tk(ptk)); event Running(~S_id, A_id, <~SNonce, ANonce, r2, ptk, gtk2>); event S_ReplayCtr(r2); event S_AcceptsMessage(~S_id, m); event S_InstallsGtk(~S_id, gtk2); // MLME-SETKEYS.request let group_msg2_contents = <'GrkHeader2', r2> in let m = in event Send(~S_id, A_id, 'Message2', r2, group_msg2_contents); event SendsCiphertext(~S_id, m, tk(ptk)); out(senc(m, tk(ptk))); event S_Branch1() ) ) let Authenticator = new ~A_id; out(~A_id); !( // Initial 4-way handshake new ~r; new ~ANonce; in(S_id); let pat_msg1_contents = <'Header1', ~r, ~ANonce> in event Send(~A_id, S_id, 'Message1', ~r, pat_msg1_contents); out(pat_msg1_contents); let ptk = CalcPTK(<~pmk, ~ANonce, SNonce, ~A_id, S_id>) in let msg2_contents = <'Header2', ~r, SNonce> in in(); event Receive(S_id, ~A_id, 'Message2', ~r, msg2_contents); new ~gtk; event A_GeneratesGtk(~gtk); event A_InstallsGtk(~gtk); // MLME-SETKEYS.request let msg3_contents = <'Header3', ~r+'1', ~ANonce, senc(~gtk, kek(ptk))> in event Send(~A_id, S_id, 'Message3', ~r+'1', msg3_contents); out(); let msg4_contents = <'Header4', ~r+'1'> in in(); event Receive(S_id, ~A_id, 'Message4', ~r+'1', msg4_contents); event A_InstallsPtk(ptk); // MLME-SETKEYS.request event Commit(~A_id, S_id, ); // Group rekey !( new ~gtk2; event A_GeneratesGtk(~gtk2); let group_msg1_contents = <'GrkHeader1', ~r+'1'+'1', senc(~gtk2, kek(ptk))> in let m = in event SendsCiphertext(~A_id, m, tk(ptk)); event Send(~A_id, S_id, 'Message1', ~r+'1'+'1', group_msg1_contents); out(senc(m, tk(ptk))); event A_InstallsGtk(~gtk2); // MLME-SETKEYS.request (( let group_msg2_contents = <'GrkHeader2', ~r+'1'+'1'> in let m = in in(senc(m, tk(ptk))); event Receive(S_id, ~A_id, 'Message2', ~r+'1'+'1', group_msg2_contents); event ReceivesCiphertext(~A_id, m, tk(ptk)); //event Commit(~A_id, S_id, ); event A_Branch1() ) + ( let group_msg1_rtx_contents = <'GrkHeader1', ~r+'1'+'1'+'1', senc(~gtk2, kek(ptk))> in let m = in event SendsCiphertext(~A_id, m, tk(ptk)); event Send(~A_id, S_id, 'Message1', ~r+'1'+'1'+'1', group_msg1_rtx_contents); out(senc(m, tk(ptk))); let group_msg2_rtx_contents = <'GrkHeader2', ~r+'1'+'1'+'1'> in let m = in in(senc(m, tk(ptk))); event Receive(S_id, ~A_id, 'Message2', ~r+'1'+'1'+'1', group_msg2_rtx_contents); event ReceivesCiphertext(~A_id, m, tk(ptk)); //event Commit(~A_id, S_id, ); event A_Branch2() )) ) ) // Main process starts here new ~pmk; (!Supplicant || Authenticator) // Uncomment to apply countermeasure for GTK. /* restriction CountermeasureKrackGtk: "All id gtk #i #j. S_InstallsGtk(id, gtk)@i & S_InstallsGtk(id, gtk)@j ==> (#i=#j)" */ restriction RestrictionCtr: "All r r2 #i #j. S_ReplayCtr(r)@i & S_ReplayCtr(r2)@j & (i (Ex x. r+x=r2)" lemma DataConfProtocolInvariant [sources]: "All id1 m k #i. ReceivesCiphertext(id1, m, k)@i ==> ( (Ex #j. KU(m)@j & (j (#i=#j)" lemma NoKrackGtk: "All id gtk #i. S_InstallsGtk(id, gtk)@i ==> not(Ex #j. S_InstallsGtk(id, gtk)@j & (j (not (Ex #j. K(ptk)@j))" // GTK is secret - It is not possible that the GTK has been installed and the adversary knows it. lemma SecretGtk: all-traces "All id gtk #i. S_InstallsGtk(id, gtk)@i ==> (not (Ex #j. K(gtk)@j))" // GTK accepted by one of the supplicants is the GTK calculated and forwarded by the authenticator. lemma ReceivedGtkSameAsGenerated: all-traces "All S gtk #i. S_InstallsGtk(S, gtk)@i ==> (Ex #j. A_GeneratesGtk(gtk)@j & (j (tid1=tid2)" // Agreement [Lowe97] // - Injective (assumed from definition) // - Full, t = // - Mutual lemma Agreement: all-traces "All X Y t #i. Commit(X, Y, t)@i ==> ( (Ex #j. Running(Y, X, t)@j & (j