verification of security protocols secrecy and authentication in proverif april 23, 2012
TRANSCRIPT
PAGE 2
Try yourself (1)
• A wants to send a secret message m to B •
A B: {|{|msg,m|}skA|}pkB
• B expects m to be secret. Is it true?
• Model in ProVerif:- A/B- Initializer- Compromised
• Find an attack and fix the protocol
PAGE 3
free net, msg, spy.private free initialInitiatorData, initialResponderData.(* The cryptographic constructors. *)fun pencrypt/2. (* public key encryption *)fun sign/2. (* digital signing *)fun enc/1. (* extracts encryption key from a key-pair *)fun dec/1. (* extracts decryption key from a key-pair *)private fun pubkeypair/1.private fun signkeypair/1.(* The cryptographic destructors. *)reduc pdecrypt(pencrypt(x,enc(y)),dec(y)) = x.reduc unsign(sign(x,enc(y)),dec(y)) = x.reduc pubkey(agent) = enc(pubkeypair(agent)).reduc unsignkey(agent) = dec(signkeypair(agent)).(* The queries. *)query attacker: flagA.query attacker: flagB.
Encoding (1)
A B: {|{|msg,m|}skA|}pkB
PAGE 4
(* Initiator process *)let initiator = in(initialInitiatorData,(a,sa)); (* initial data*) !in(net, b); (* get responder's name*) if a<>b then let pb = pubkey(b) in new m; (if b<>spy then new flagA; out(m,flagA)) | let signed = sign((msg,m),sa) in out(net, (a, b, pencrypt(signed,pb))).(* Responder process. *)let responder = in(initialResponderData, (b,db)); in(net, (a,=b,encrypted)); let va = unsignkey(a) in let signed = pdecrypt(encrypted,db) in let (=msg,m) = unsign(signed,va) in if a<>spy then new flagB; out(m,flagB).
Encoding (2)
A B: {|{|msg,m|}skA|}pkB
Notice again that we are sending flagA on the “secret channel” given by m. And that there is a “if b <> spy” conditional before. This is because we are checking for internal attacker (and since the spy is an internal, she can always get hold of m).
PAGE 5
(* Initializer process – initial data are sent over a trusted channel *)let initializer = new agent in (* generate agent name *) let pkp = pubkeypair(agent) in (* compute public encryption keypair *) let skp = signkeypair(agent) in (* compute signing keypair *) out(initialInitiatorData, (agent,enc(skp))); (*launch initiator role*) out(initialResponderData, (agent,dec(pkp))); (*launch responder role*) out(net, (agent, enc(pkp), dec(skp))). (* publish the public data *)
(* The compromised agent. *)let compromised = let pkp = pubkeypair(spy) in (* compute public encryption keypair *) let skp = signkeypair(spy) in (* compute signing keypair *) out(net, (pkp,skp)). (* publish the keypairs to model compromise *)
(* The system. *)process !initiator | !responder | compromised | !initializer
Encoding (3)
A B: {|{|msg,m|}skA|}pkB
PAGE 6
• AttackA M: {|{|msg,m|}skA|}pkM
M(A) B: {|{|msg,m|}skA|}pkB
• The fixA B: {|{|pkB,msg,m|}skA|}pkB
Attack / Fix
PAGE 7
Try yourself (2)
• Consider the following protocol (pkB is the public key of B):A B: AB A: NA B: {s;N}pkB
• B expects that s is a secret that he shares with A• Model this protocol in ProVerif: express B's secrecy expectation as a
conditional secrecy assertion• Is the conditional secrecy of s guaranteed in the internal threat
model? If not, write down the attack trace and fix the protocol
PAGE 8
free net,spy.private free initialInitiatorData, initialResponderData.
(* The cryptographic constructors. *)fun pencrypt/2. (* public key encryption *)fun sign/2. (* digital signing *)fun enc/1. (* extracts encryption key from a key-pair *)fun dec/1. (* extracts decryption key from a key-pair *)
(* The cryptographic destructors. *)reduc pdecrypt(pencrypt(x,enc(y)),dec(y)) = x.reduc unsign(sign(x,enc(y)),dec(y)) = x.
(* A constructor that maps agents to their secret keypairs. *)private fun pubkeypair/1.private fun signkeypair/1.
Encoding (1)A B: AB A: NA B: {s;N}pkB
PAGE 9
reduc pubkey(agent) = enc(pubkeypair(agent)).(* unsignkey/1. *)reduc unsignkey(agent) = dec(signkeypair(agent)).
(* The queries. *)query attacker: s.query attacker: flagA.query attacker: flagB.
let initializer = new agent; let pkp = pubkeypair(agent) in let skp = signkeypair(agent) in out(initialInitiatorData, (agent,enc(skp))); out(initialResponderData, (agent,dec(pkp))); out(net, (agent, enc(pkp), dec(skp))).
Encoding (2)A B: AB A: NA B: {s;N}pkB
PAGE 10
let initiator = in(initialInitiatorData, (a,sa)); in(net, (b,encb,unsb)); if a<>b then if encb = pubkey(b) then new s; (if b <> spy then new flagA; out(s,flagA)) | out(net,a); in(net,n); out(net,(pencrypt(s,n),encb)).
let responder = in(initialResponderData, (b,db)); in(net,a); if a<>b then new n; out(net,n); in(net, (encrypted)); let (s,=n) = pdecrypt(encrypted,db) in if a <> spy then new flagB; out(s,flagB).
Encoding (3)A B: AB A: NA B: {s;N}pkB
This is put in parallel, but we could also put this in sequence with the rest (I think).
PAGE 11
let compromised = let pkp = pubkeypair(spy) in let skp = signkeypair(spy) in out(net, (pkp,skp)).
process !initiator | !responder | compromised | !initializer
Encoding (4)A B: AB A: NA B: {s;N}pkB
PAGE 12
• AttackM(A) B: AB M(A): NM(A) B: {|s;N|}pkB
• Secrecy s? NO! (spy)• Secrecy flagA? NO!• Secrecy flagB? NO!
• Solution A B: {|{|s;B;N|}skA|}pkB
Attack / Fix
A B: AB A: NA B: {|{|s;B;N|}skA|}pkB
A B: AB A: NA B: {s;N}pkB
There are other solutions, but we have to aim at the most simple solution possible (also in the exam, don’t start putting encryption everywhere).
PAGE 13
let initiator = [...] if a<>b then if encb = pubkey(b) then new s; (if b <> spy then new flagA; out(s,flagA)) | out(net,a); in(net,n); out(net,
(pencrypt(sign((s,b,N),sa),encb))).
let responder = [...] in(net, (signedencrypted)); let signed = pdecrypt(signedencrypted,db) in let (s,=b,=N) = unsign(signed, unsignkey(a)) in if a <> spy then new flagB; out(s,flagB).
Exercise 4: secrecy?
Secrecy s? NO! (spy!)Secrecy flagA? YES!Secrecy flagB? YES!
A B: AB A: NA B: {|{|s;B;N|}skA|}pkB
PAGE 14
Try yourself (3)
• Consider the following protocol, with kA a symmetric key shared by A and server S, and kB a symmetric key shared by B and S:
A B : (A;B;{Na;B}kA)
B S : (A;B;{Na;B}kA;{Nb;B}kB)
S B : ({Na;k}kA;{Nb;k}kB)
B A : ({Na;k}kA)
• Model this protocol in ProVerif• At the end of the protocol, A and B should be able to communicate
secretly by using the newly established key k: study the strong secrecy of k and fix the protocol if necessary
• Note that there are only 3 agents
PAGE 15
fun encrypt/2.reduc decrypt(encrypt(m,k),k) = m.fun host/1.private reduc getkey(host(x)) = x.
free c.private free secretA, secretB.private free k.noninterf k.
let processA = in(c, hostB0); new Na; out(c, (hostA, hostB0, encrypt((Na, hostB0), kA)));
in(c, (m2));let (=Na, k) = decrypt(m2, kA) in if hostB0 = hostB then
out(c, encrypt(secretA, k)).
Encoding (1)A B: (A;B;{Na;B}kA)B S: (A;B;{Na;B}kA;{Nb;B}kB)S B: ({Na;k}kA;{Nb;k}kB)B A: ({Na;k}kA)
PAGE 16
let processB = in(c, (hostA1, =hostB, m2));new Nb;out(c, (hostA1, hostB, m2, encrypt((Nb, hostB), kB)));in(c, (m3, m4));let (=Nb, k) = decrypt(m4, kB) in
out(c, (m3)); if hostA1 = hostA then out(c, encrypt(secretB, k)).
let processS = in(c, (hostA1, hostB1, m2, m3)); let (Na1, =hostB1) = decrypt(m2, getkey(hostA1)) in
let (Nb1, =hostB1) = decrypt(m3, getkey(hostB1)) in out(c, (encrypt((Na1, k), getkey(hostA1)), encrypt((Nb1, k), getkey(hostB1)))).
Encoding (2)A B: (A;B;{Na;B}kA)B S: (A;B;{Na;B}kA;{Nb;B}kB)S B: ({Na;k}kA;{Nb;k}kB)B A: ({Na;k}kA)
PAGE 17
process new kA; new kB; let hostA = host(kA) in let hostB = host(kB) in out(c, hostA); out(c, hostB); ((!processA) | (!processB) | (!processS))
Encoding (3)
Noninterf? NO! The attacker can impersonate A and get k
A B: (A;B;{Na;A;B}kA)B S: (A;B;{Na;A;B}kA;{Nb;B}kB)S B: ({Na;k}kA;{Nb;k}kB)B A: ({Na;k}kA)
A B: (A;B;{Na;B}kA)B S: (A;B;{Na;B}kA;{Nb;B}kB)S B: ({Na;k}kA;{Nb;k}kB)B A: ({Na;k}kA)
PAGE 18
Noninterf? YES!
noninterf secretA, secretB.
let processA = [...] out(c, (hostA, hostB0, encrypt((Na, hostA, hostB0), kA)));
[...]
let processB = [...]
out(c, (hostA1, hostB, m2, encrypt((Nb, hostA1, hostB), kB)));[...]
let processS = in(c, (hostA1, hostB1, m2, m3)); let (Na1, =hostA1, =hostB1) = decrypt(m2, getkey(hostA1)) in
let (Nb1, =hostA1, =hostB1) = decrypt(m3, getkey(hostB1)) in new k;
[...]
Encoding (4)
A B: (A;B;{Na;A;B}kA)B S: (A;B;{Na;A;B}kA;{Nb;B}kB)S B: ({Na;k}kA;{Nb;k}kB)B A: ({Na;k}kA)
PAGE 19
• Queries (properties you want to verify) must be declared in the declaration section
• Today we study:- Secrecy: queries if the attacker can obtain M
− query attacker : M- Many-one correspondence: queries if event M is always preceded by event N
− query ev: M ==> ev: N (∀ parameters)- One-one correspondence: queries if event M is always preceded by event N,
and every trace contains at least as many N-events as M-events− query evinj: M ==> evinj: N
Queries
PAGE 20
query ev: endSend(x,y,z) ==>ev: beginSend(x,y,z).
=
query (∀ x,y,z) (ev:endSend(x,y,z) ==>ev: beginSend(x,y,z)).
Authentication and correspondence properties
PAGE 21
B A: {|B;n;m1|}pkA
A B: {|B;n;m2|}skA
• Does A authenticates to B?=
• Goal: if one of the parties thinks that the exchange (A;B;m1;m2) happened, then this exchange should have indeed started sometime in the past
Example: a simple authentication protocol
PAGE 22
free c, A, B.private free skA, skB.fun pk/1.fun enc/2.fun sign/2.reduc dec(enc(x,pk(y)),y) = x.reduc check(sign(x,y),pk(y)) = x.
query ev:end(w,x,(y,z)) ==> ev:begin(w,x,(y,z)).
let initiatorB = new nB; new m1B; out(c,enc((B,nB,m1B),pk(skA))); in(c,x); let (=B,=nB,m2)=check(x,pk(skA)) in event end(A,B,(m1B,m2)).
Example: a simple authentication protocol
B A: {|B;n;m1|}pkA
A B: {|B;n;m2|}skA
PAGE 23
let responderA =in(c,x);let (=B,nonce,m1)=dec(x,skA) in
new m2A; event begin(A,B,(m1,m2A)); out(c,sign((B,nonce,m2A),skA)).
process out(c,pk(skA)); out(c,pk(skB)); (!responderA | !initiatorB)
Example: a simple authentication protocol
B A: {|B;n;m1|}pkA
A B: {|B;n;m2|}skA
Check this out. Having “=B” in the let means that A knows B;s name beforehand, which is in general an assumption we CANNOT make.
PAGE 24
• Answer: ev: end(w,x,(y,z)) ==>
ev: begin(w,x,(y,z)) is false.
• Attack:B A: {|B;n;m1|}pkA
A M: {|B;n;m2|}skA
M knows n (B, m2)
M A: {|B;n;mm|}pkA
A B: {|B;n;m2|}skA
Example: a simple authentication protocol
B A: {|B;n;m1|}pkA
A B: {|B;n;m2|}skA
PAGE 25
B A: {|B;n;m1|}pkA
A B: {|B;n;m1;m2|}skA
• Now the same attack is not possible:B A: {|B;n;m1|}pkA
A M: {|B;n;m1;m2|}skA
M knows n (B, m2)
M A: {|B;n;mm|}pkA
A B: {|B;n;mm;m2|}skA
Example: a simple authentication protocol - Fixed
PAGE 26
• We want to include a compromised agent called spy, publishing the spy’s secrets
• We need to use conditional end-events:
... (if a<>spy then event endSend(a,b,m)) | ...
instead of
... event endSend(a,b,m); ...
• Why? The latter is trivially violated for a=spy.
Modeling internal threats
PAGE 27
Other ProVerif features
• A public key certificate is a pair of an agent name A and her public key pA digitally signed by the key ca of a trusted certificate authority.
• In ProVerif: sign((A; pA); ca)
PAGE 28
• ProVerif allows to insert phase separators into processes:...; phase n; ...where n is a positive integer
• The phase separator indicates that the process now enters phase n
• When a process starts running, it is in phase 0
• When a process enters the next phase, all processes that have not yet reached the end of the previous phase are discarded
• In that sense, one can understand the phase separators as global synchronization commands
Other ProVerif features
PAGE 29
• You can query for standard secrecy up to the end of a certain phase:
query attacker: x phase n.
• This queries if x remains secret up to the end of phase n.• The query is violated if an attacker can get x before the process has
started executing phase n+1.
Other ProVerif features
PAGE 30
Other ProVerif features
• Non-interference allows us to reason about the secrecy of guessable messages that are meant to be kept secret.- Example: Electronic votes. These are easily guessable, because in a typical
election there is only a small number of candidates.• Standard secrecy is often appropriate for reasoning about messages
that are virtually impossible to guess.- Example: Cryptographic session keys.
• Somewhat in between are weak secrets. These are impossible to guess online, but offline attacks are possible.- Example: Passwords.- An offline attack works by first collecting some data online and then running a
computationally intensive analysis offline.- Example: Searching a dictionary for likely passwords.- Query in ProVerif: weaksecret w.
PAGE 31
Other ProVerif features
• ProVerif can soundly verify testing equivalence (observational equivalence).
• ProVerif verification of testing equivalence is incomplete.- This incompleteness does show in practice (much more often than the
incompleteness for standard secrecy and correspondence assertions).• To query for testing equivalence of two processes, you need to
express the two processes “as one”. ProVerif choice-construct tells ProVerif the spots where the two processes differ:
• M,N Msg ::= ... | choice[M,N] | ...∈- fst(P): process obtained from P by replacing every occurrence of choice[M,N] by
M- snd(P): process obtained from P by replacing every occurrence of choice[M,N]
by N- ProVerif tries to prove fst(P) snd(P).≃
PAGE 32
• In principle, you can query for observational equivalence of arbitrary processes P and Q using the choice construct:
R = if choice[m,n] = m then P else Q
Then fst(R)≃snd(R) iff P≃Q
• However, ProVerif is usually unable to verify fst(R)≃snd(R) due to its incompleteness
Other ProVerif features
PAGE 33
fun hash/1.free net.process new n; out(net, choice[n, hash(n)]).
• This asks ProVerif to prove:new n; out(net, n)≃new n; out(net, hash(n)).
• ProVerif succeeds on this.• Intuitively, this equivalence holds, because to an observer both n
and hash(n) look completely arbitrary.
Other ProVerif features
PAGE 34
free net,n,m.
process out(net, choice[n,m]); out(net, choice[m,n])
• This asks ProVerif to prove:out(net,n); out(net,m)≃out(net,m); out(net,n)
• These are not equivalent
Other ProVerif features
PAGE 35
Do it yourself
• Consider the following protocol:B A : nb;text1A: begin(A,B,nb)A B : pkA;A;{na;nb;text2}skA
B: end(A,B,nb)B: begin(B,A,na)B A : pkB;B;{na;text3}skB
A: end(B,A,na)- A public-key infrastructure is assumed: pkA, pkB are the public keys of A and B, respectively- skA, skB are the signing keys of A and B, respectively- text1,text2,text3 are publicly known messages
• Write a model of this protocol in ProVerif• Check whether the protocol correctly realizes mutual authentication between A
and B; fix it if needed