All Downloads are FREE. Search and download functionalities are using the official Maven repository.

models.examples.case_studies.iolus.als Maven / Gradle / Ivy

module examples/case_studies/iolus

/*
 * This is a model of Iolus, a scheme for secure multicasting.
 * In this scheme, nodes multicast messages to other nodes
 * within a group whose membership changes dynamically. The
 * group is partitioned into subgroups, arranged in a tree,
 * each with its own Key Distribution Server (KDS).
 *
 * For a detailed description, see:
 *   Mana Taghdiri, "Lightweight Modelling and Automatic Analysis
 *   of Multicast Key Management Schemes", Masters Thesis, Dept.
 *   of EECS, MIT, Dec. 2002.
 *   http://sdg.lcs.mit.edu/pubs/theses/taghdiri_masters.pdf
 *
 * author: Mana Taghdiri
 */

open util/ordering[Tick] as ord

sig Tick {}

/**
 * It can be abstract, since the fact below says Key=GroupKey
 */
abstract sig Key {}

/**
 * It can be abstract, since the fact below says Message=DataMessage
 */
abstract sig Message {
  sender : Member,
  sentTime : Tick,
  key : Key
}

/**
 * It can be abstract, since the fact below says KDS=GSA
 */
abstract sig KDS {
  keys : Tick -> Key,
  members : Tick -> Member
}{
  Monotonic[keys]
  all t : Tick | let t' = ord/prev[t] {
    all m : members[t]-members[t'] | Join[m, t, this]
    all m : members[t']-members[t] | Leave[m, t]
  }
}

/**
 * It can be abstract, since the fact below says "Member=Client"
 */
abstract sig Member {
  ownedKeys : Tick -> Key,
  receivedMessages : Tick -> Message
}{
  Monotonic[ownedKeys]
  Monotonic[receivedMessages]
}

fact MemberBehavior {
  Init[ord/first]
  all m : Member, t : Tick - ord/first |
    (some msg : Message |
      SendMessage[m, t, msg] || ReceiveMessage[m, t, msg]) ||
    (some kds : KDS | Join[m, t, kds]) ||
    Leave[m, t] || MemberInactive[m, t]
}

pred Monotonic[r : Tick -> univ] {
  all t : Tick | ord/prev[t].r in t.r
}

----------------------------------------------
sig GroupKey extends Key {
  generator : GSA,
  generatedTime : Tick
}{
  some c : Client |
   (Join[c, generatedTime, c.server] || Leave[c, generatedTime]) &&
   c.server = generator
}

sig DataMessage extends Message {
  gsaID : GSA,
  retransmitTime : Tick }
{ SendMessage[sender, sentTime, this] ||
  (some msg' : DataMessage |
     Remulticast[gsaID, msg', retransmitTime, this]) }

sig GSA extends KDS {
  parent : lone GSA }
{ keys[Tick].generator = this
  all t : Tick, k : keys[t] - keys[ord/prev[t]] |
    k.generatedTime = t }

sig Client extends Member {
  server : GSA }
{ all t : Tick, k : ownedKeys[t] - ownedKeys[ord/prev[t]] |
    k.generator = server && k.generatedTime = t }

fact IolusProperties {
  no k, k' : GroupKey | k!=k' && k.generator = k'.generator && k.generatedTime = k'.generatedTime
  all g : GSA, msg : DataMessage, t : Tick | RemulticastConditions[g, msg, t] =>
    (some msg': DataMessage | Remulticast[g, msg, t, msg'])
}

fact GSATree {
  let root = {g : GSA | no g.parent} {
    one root
    GSA in root.*~parent }}

fact {
  Member = Client
  KDS = GSA
  Message = DataMessage
  Key = GroupKey
  no m, m' : DataMessage {
    m!=m'
    m.sender = m'.sender
    m.sentTime = m'.sentTime
    m.key = m'.key
    m.gsaID = m'.gsaID
    m.retransmitTime = m'.retransmitTime }
}

----------------------------------------------
pred Init[t : Tick] {
  no Member.receivedMessages[t]
  no Member.ownedKeys[t]
  no KDS.keys[t]
  no KDS.members[t] }

pred Join[m : Member, t : Tick, kds : KDS] {
  kds = m.server
  JoinRequest[m, kds, t]
  NoChange[m.receivedMessages, t]
}
pred JoinRequest[c : Client, gsa : GSA, t : Tick] {
  c !in gsa.members[ord/prev[t]]
  KeyUpdate[gsa, t]
  c in gsa.members[t] }

pred Leave[m : Member, t : Tick] {
  LeaveRequest[m, m.server, t]
  NoChange[m.receivedMessages, t] }

pred LeaveRequest[c : Client, gsa : GSA, t : Tick] {
    c in gsa.members[ord/prev[t]]
    KeyUpdate[gsa, t]
    c !in gsa.members[t] }

pred SendMessage[m : Member, t : Tick, msg : Message] {
  SendRequest[m, m.server, t, msg]
  m.receivedMessages[t] = m.receivedMessages[ord/prev[t]] + msg
  ConstantMembership[m, t] }

pred SendRequest[c : Client, gsa : GSA, t : Tick, msg : DataMessage] {
  c in gsa.members[t]
  msg.sender = c
  msg.sentTime = t
  NewestKey[gsa.keys[t], msg.key]
  msg.gsaID = gsa
  msg.retransmitTime = t
  (some gsa.parent.members[t]) =>
    (some msg' : DataMessage | Remulticast[gsa, msg, t, msg']) }

pred ReceiveMessage[m : Member, t : Tick, msg : Message] {
  ReceiveConditions[m, t, msg]
  m.receivedMessages[t] = m.receivedMessages[ord/prev[t]] + msg }

pred MemberInactive[m : Member, t : Tick] {
  NoChange[m.receivedMessages, t] --does not constrain owned keys
  ConstantMembership[m, t] }

pred ReceiveConditions[m : Member, t : Tick, msg : Message] {
  ConstantMembership[m, t]
  msg !in m.receivedMessages[ord/prev[t]]
  msg.retransmitTime in ord/prevs[t]
  msg.key in m.ownedKeys[t] }

pred CanReceive[m : Member, t : Tick, msg : Message] {
  some msg' : DataMessage {
    msg'.sentTime = msg.sentTime
    msg'.sender = msg.sender
    msg' in m.receivedMessages[ord/prev[t]] || ReceiveConditions[m, t, msg'] }}

pred IsMember[m : Member, t : Tick] {
  some kds : KDS | m in kds.members[t]
}

-------------------------------------------
pred RemulticastConditions[g : GSA, msg : DataMessage, t : Tick] {
  msg.retransmitTime in ord/prevs[t]
  msg.key in g.keys[t] + g.parent.keys[t]
  some g.parent + g - msg.gsaID }

pred Remulticast[g : GSA, msg : DataMessage, t : Tick, msg': lone DataMessage] {
  RemulticastConditions[g, msg, t]
  let g' = g.parent + g - msg.gsaID | NewestKey[g'.keys[msg.sentTime], msg'.key]
  msg'.sender = msg.sender
  msg'.sentTime = msg.sentTime
  msg'.retransmitTime = t
  msg'.gsaID = g
}

pred KeyUpdate[g : GSA, t : Tick] {
  some k : Key {
    GeneratedKey[g, t, k]
    all c : Client | c in g.members[t] <=> k in c.ownedKeys[t]
    k in g.keys[t] }}

pred NewestKey[keys : set GroupKey, newest: lone GroupKey] {
  some keys <=> some newest
  newest in keys
  no ord/nexts[newest.generatedTime] & keys.generatedTime }

pred GeneratedKey[g : GSA, t : Tick, key : GroupKey] {
  key.generator = g
  key.generatedTime = t
}

pred ConstantMembership[c : Client, t : Tick] {
  IsMember[c, t] <=> IsMember[c, ord/prev[t]] }


pred NoChange[r : Tick -> univ, t : Tick] {
  r[ord/prev[t]] = r[t]
}

--------------------------------------------
assert Acyclic {
  all g : GSA | g !in g.^parent }

//check Acyclic for 6 -- one min

assert Connected {
  all g, g' : GSA | g in g'.*(parent + ~parent) }

//check Connected for 6

assert TimeProceeds {
  no msg : DataMessage | msg.retransmitTime in ord/prevs[msg.sentTime] }

//check TimeProceeds for 6

pred LoopFree {
  no t, t' : Tick {
    t!=t'
    all k : KDS | k.members[t] = k.members[t'] -- no constraint on keys
    all m : Member | m.receivedMessages[t] = m.receivedMessages[t']
    all m : DataMessage | m.retransmitTime = t =>
      (some m' : DataMessage {
        m'.retransmitTime = t'
        m.sender = m'.sender
        m.sentTime = m'.sentTime
        m.gsaID = m'.gsaID
        m.key = m'.key })
    }}

//fact NoLoop { LoopFree() } -- Property-specific diameter

------------------------------------------------
assert loop {
  !LoopFree }
//check loop for 13 but 2 Member, 1 KDS, 1 Message

assert NonLinearTopology {
  (no g : GSA | #g.~parent > 1) ||
  !(some m, m' : DataMessage | Remulticast[m.gsaID, m', m.retransmitTime, m]
    && !SendMessage[m.sender, m.sentTime, m]
    && (some c : Client | m in c.receivedMessages[ord/nexts[m.retransmitTime]]))}

//check NonLinearTopology for 5 but 3 KDS, 3 Member, 2 Message -- > good scenario

assert NotOutside {
  no msg : DataMessage | !IsMember[msg.sender, msg.sentTime] }

//check NotOutside for 5

assert Trivial {
  0 = 1 }

//check Trivial for 2 but 1 KDS

assert x {
  !(LoopFree && some DataMessage &&
     (some t : Tick | some m, m' : Member |
        m!=m' && IsMember[m, t] && IsMember[m', t] && t != ord/next[ord/first]))
}

//check x for 3 but 2 Member, 2 KDS, 2 Message
 -------------------------------------------
assert OutsiderCantRead {
  no msg : Message, m : Member, t : Tick {
    IsMember[msg.sender, msg.sentTime]
    !IsMember[m, msg.sentTime]
    CanReceive[m, t, msg]
  }
}
assert OutsiderCantSend {
  no msg : Message, m : Member, t : Tick {
    !IsMember[msg.sender, msg.sentTime]
    IsMember[m, t]
    msg !in m.receivedMessages[ord/prev[t]]
    CanReceive[m, t, msg]
  }
}
assert InsiderCanRead {
  all msg : Message, m : Member |
    some t : Tick - ord/last | all t' : ord/nexts[t] |
      (IsMember[msg.sender, msg.sentTime] &&
       IsMember[m, msg.sentTime]) => CanReceive[m, t', msg]
}

check OutsiderCantRead for 5 but 3 Member expect 0
//check OutsiderCantSend for 5 but 3 Member -- 5 min
//check InsiderCanRead for 9 but 2 Member, 1 KDS, 1 Message
//check InsiderCanRead for 10 but 2 Member, 2 KDS, 2 Message -- not able to check




© 2015 - 2025 Weber Informatics LLC | Privacy Policy