packages feed

tamarin-prover-0.8.4.0: data/examples/ake/bilinear/Scott.spthy

theory Scott
begin

builtins: bilinear-pairing

functions: kdf/1, hp/1

section{* Scott: MTI-C0 like identity based key exchange protocol *}

/*
 * Protocol:	Scott
 * Modeler: 	Benedikt Schmidt
 * Date: 	May 2012
 * Source:	Boyd overview identity based key exchange protocols
 *
 * Status: 	Working
 */


// Key generation center

rule KGC_Setup:
  [ Fr( ~msk ) ]
  --[ KGCSetup() ]->
  [ !MSK( ~msk ) ]

rule KGC_request:
  [ !MSK( ~msk ) ]
  -->
  [ !LTK( $ID, pmult( ~msk, hp($ID) ) ) ]


// Reveals

rule Reveal_ltk:
  [ !LTK( $ID, skID ) ]
  --[ LtkRev($ID) ]->
  [ Out(skID) ]

rule Reveal_master_key:
  [ !MSK( ~msk ) ]
  --[ MskRev() ]->
  [ Out( ~msk ) ]

rule Reveal_session_key:
  [ !Sessk( ~ey, sek ) ]
  --[ SesskRev( ~ey ) ]->
  [ Out( sek ) ]


// Protocol

rule Init_1:
  let skA = pmult( ~s, hp($A) )
      X   = em( skA, hp($B) )^~ex
  in 
  [ Fr( ~ex )
  , !LTK( $A, skA )
  ]
  -->
  [ Init( ~ex, $A, $B, X )
  , Out( X )
  ]

rule Init_2:
  let sessKey = kdf( Y^~ex, $A, $B, X, Y )
  in
  [ Init( ~ex, $A, $B, X )
  , In( Y )
  ]
  --[ Accept( ~ex, $A, $B, sessKey )
    , Sid( ~ex, <'Init',$A,$B,X,Y> )
    // a matching session for ~ex has the following sid
    , Match( ~ex, <'Resp',$B,$A,X,Y> )
    ]->
  [ !Sessk( ~ex, sessKey ) ]


rule Resp_1:
  let skB     = pmult( ~s, hp($B))
      Y       = em(hp($A), skB)^~ey
      sessKey = kdf(X^~ey, $A, $B, X, Y)
  in
  [ Fr( ~ey )
  , !LTK( $B, skB )
  , In( X )
  ]
  --[ Accept( ~ey, $B, $A, sessKey )
    , Sid( ~ey, <'Resp',$B,$A,X,Y> )
    // a matching session for ~ey has the following sid
    , Match( ~ey, <'Init',$A,$B,X,Y> )
    ]->
  [ Out( Y )
  , !Sessk( ~ey, sessKey )
  ]


lemma key_agreement_reachable:
  exists-trace
  "Ex #i #j A B SID t1 t2 k.
        Accept(t1, A, B, k)  @ i
      & Match(t1,  SID) @ i
      & Accept(t2, B, A, k)   @ j
      & Sid(t2, SID)   @ j"



lemma key_secrecy:
  /* 
   * We do not consider ephemeral key reveals here.
   * There is a simple attack where another session of
   * A is used to get em(hp(A), hp(B))^s which is then sent
   * to A as Y. Then A uses X = em(hp(A), hp(B))^(s*ex) as
   * input for the kdf.
   * 
   * If there exists a Test session whose key k is known to the
   * Adversary, then...
   */
  "(All #i1 #i2 test A B k.
    Accept(test, A, B, k) @ i1 & K( k ) @ i2
    ==> ( 
    // ... the test session must be "not clean".
    // test is not clean if one of the following has happened:
    //
    // session-key-reveal of test thread.
      (Ex #i3. SesskRev( test ) @ i3 )
    
    // more than one KGC
    | (Ex #i3 #i4. KGCSetup() @ i3 & KGCSetup() @ i4 & not (#i3 = #i4))
    
    // there is a matching session
    | (Ex matching #i3 #i4 sid.
    	   // matching's 'sid' info matches with test
           ( Sid ( matching, sid ) @ i3 & Match( test, sid ) @ i4)
	   & ( 
             // matching's session key was revealed
	       (Ex #i5. SesskRev( matching ) @ i5 )
	   )
      )

    // there is no matching session
    | (  (not (Ex matching #i3 #i4 sid.
    	   // matching's 'sid' info matches with test
           ( Sid ( matching, sid ) @ i3 & Match( test, sid ) @ i4)))

        & (  
          // the longterm key of test.peer was revealed
            (Ex #i5. LtkRev( B ) @ i5 )

          // the longterm key of test.actor was revealed
          | (Ex #i3. LtkRev(A) @ i3 )
          
          // the master key was revealed
          | (Ex #i3. MskRev() @ i3)
          )
      )

    )
  )"

end