packages feed

tamarin-prover-0.8.0.0: data/examples/related_work/TPM_DKRS_CSF11/Envelope.spthy

theory TPM_Envelope begin

text{* Envelope protocol example from:

[1] Stephanie Delaune, Steve Kremer, Mark D. Ryan, Graham Steel, "Formal
Analysis of Protocols Based on TPM State Registers," csf, pp.66-80, 2011 IEEE
24th Computer Security Foundations Symposium, 2011.

Modeler: Simon Meier
Date:    June 2012
Status:  No automatic proof (interactive proof possible)

Note that this model incorporates an arbitrary number of reboots, which is an
open problem in [1]. The verification relies on the construction that we track
all writes to the PCR-fact using the additional PCR_Write-fact. This allows us
then to descend in the hash chain by solving PCR_Write-premises.

*}

builtins: signing, asymmetric-encryption, hashing

// TPM platform configuration register (PCR) model
// Here, we model only one PCR. Modelling multiple PCR's can be done by
// parametrizing their facts on an additional term used to identify them.
rule PCR_Init:
    [ Fr(~aik)             // Authentication identity key
    ]
  --[
      PCR_Init()           // Used in property to ensure at most one initialization
    , PCR_Write('pcr0')
    ]->
    [ PCR('pcr0')          // the initial PCR value is 'pcr0'
    , PCR_Write('pcr0')    // We also track the writes.
    , !AIK(~aik)           // the auth. id. key is persistent
    , Out(pk(~aik))        // publish the public key of the auth. id. key
    ]

// reset the PCR to 'pcr0'
rule PCR_Reboot:
    [ PCR(x)
    , PCR_Write(x)
    ]
  --[ PCR_Write('pcr0')
    ]->
    [ PCR_Write('pcr0')
    , PCR('pcr0')
    ]

// Extend the hash-chain in the PCR
rule PCR_Extend:
    [ PCR_Write(x)       // Get write access
    , PCR(x)             //
    , In(y)              // The adversary can present any value.
    ]
  --[ PCR_Write(h(x,y))
    ]->
    [ PCR(h(x,y))
    , PCR_Write(h(x,y))
    ]

// Certify a key together with the value it is locked to.
rule PCR_CertKey:
    [ !AIK(aik)
    , !KeyTable(lock, sk)
    ]
  --[ ]->
    [ Out(sign{'certkey', lock, pk(sk)}aik)
    ]

// Quote the current value of the PCR
rule PCR_Quote:
    [ PCR(x)
    , !AIK(aik)
    ]
  --[ PCR_Read(x)
    ]->
    [ Out(sign{'certpcr', x}aik)
    , PCR(x)
    ]

// Decrypt a message encrypted with a key locked to the CURRENT value of the
// PCR.
rule PCR_Unbind:
    [ PCR(x)
    , !KeyTable(x, sk)
    , In( aenc{m}pk(sk) )
    ]
  --[ PCR_Unbind(x,sk,m)
    , PCR_Read(x)
    ]->
    [ PCR(x)
    , Out(m) ]

// Alice

// Alice starts by communicating with Bob's PCR to setup a unique root ~n in
// the hash-chain for the following envelope protocol.
rule Alice1:
    [ Fr(~n)
    , PCR(x)
    , PCR_Write(x)
    ]
  --[ PCR_Write(h(x,~n))
    ]->
    [ PCR(h(x,~n))
    , PCR_Write(h(x,~n))
    , Alice1(~n)
    ]

// Bob sends Alice a certified key locked to the value
//   h(h('pcr0',n),'obtain')
// to obtain a secret in an envelope. Note that we only allow for one session
// per reboot as [1].
rule Alice2:
    [ Alice1(n)
    , Fr(~s)
    , !AIK(aik)
    , In(sign{'certkey', h(h('pcr0',n),'obtain'), pk}aik)
    ]
  --[ Secret(~s)
    ]->
    [ Out(aenc{~s}pk)
    , Alice2(n,~s)
    ]

// Bob can use the PCR to prove to Alice that he didn't access the secret.
rule Alice3:
    [ Alice2(n,s)
    , !AIK(aik)
    , In(sign{'certpcr', h(h('pcr0',n),'deny')}aik)
    ]
  --[ Denied(s) ]->
    []

// We use the adversary to simulate Bob. He uses ordinary message deduction
// and it can create keys locked to specific values of the PCR.
rule CreateLockedKey:
    [ PCR(x)
    , Fr(~sk)
    , In(lock) // multiple keys can be locked to the same PCR value.
    ]
  --[ PCR_Read(x)
    ]->
    [ PCR(x)
    , !KeyTable(h(x,lock), ~sk)
    , Out(pk(~sk))
    ]

// Automatically proven
lemma types [typing]:
    // Values created by the PCR_Unbind rule
  " (All m d1 d2 #i. PCR_Unbind(d1, d2, m) @ i ==>
        (Ex #j. KU(m) @ j & j < i)
      | (Ex #j. Secret(m) @ j)
    )
  "

// Automatically proven
lemma PCR_Write_charn [reuse, use_induction]:
    // Values read from the PCR have been written to it beforehand.
  " (All x #i. PCR_Read(x) @ i ==>
      (Ex #j. PCR_Write(x) @ j)
    )
  "

// Assuming that there is at most one instance of the PCR,
// the adversary (playing Bob) must not know a secret that Alice created and
// thinks that access to it was denied.
//
// Currently, we have to construct its proof manually. The key argument relies
// on following the PCR_Write-premises once their presence has been
// established via the PCR_Write_charn lemma.
lemma reachable_Denied:
  "(All #i #j. PCR_Init() @ i & PCR_Init() @ j ==> #i = #j)
   ==>
   not(Ex s #i #j #k. Secret(s) @ i & Denied(s) @ j & K(s) @ k)"


end