From 0548cef05d14d85280a3ca2c70576f9becd90f7e Mon Sep 17 00:00:00 2001 From: Matthew Hutchings <mwh1g17@soton.ac.uk> Date: Mon, 20 Apr 2020 12:43:46 +0100 Subject: [PATCH] ScytherBox v1.0 First complete iteration of the scytherbox, files contain all the information required to install the scytherbox virtual machine using vagrant --- Vagrant Files/Vagrantfile | 73 ++ Vagrant Files/files/scyther/.gitignore | 4 + Vagrant Files/files/scyther/Changelog.txt | 159 ++++ .../scyther/GNU-General-Public-License.txt | 339 +++++++ Vagrant Files/files/scyther/Gui/About.py | 137 +++ .../files/scyther/Gui/Attackwindow.py | 330 +++++++ Vagrant Files/files/scyther/Gui/Editor.py | 195 ++++ Vagrant Files/files/scyther/Gui/Error.py | 51 + Vagrant Files/files/scyther/Gui/Icon.py | 52 + Vagrant Files/files/scyther/Gui/Mainwindow.py | 322 +++++++ Vagrant Files/files/scyther/Gui/Makeimage.py | 180 ++++ Vagrant Files/files/scyther/Gui/Misc.py | 90 ++ Vagrant Files/files/scyther/Gui/Preference.py | 240 +++++ .../files/scyther/Gui/Scytherthread.py | 543 +++++++++++ .../files/scyther/Gui/Settingswindow.py | 196 ++++ Vagrant Files/files/scyther/Gui/Temporary.py | 64 ++ Vagrant Files/files/scyther/Gui/Version.py | 1 + Vagrant Files/files/scyther/Gui/__init__.py | 19 + Vagrant Files/files/scyther/INSTALL.md | 96 ++ Vagrant Files/files/scyther/INSTALL.txt | 85 ++ .../files/scyther/Images/scyther-gui-16.ico | Bin 0 -> 1150 bytes .../files/scyther/Images/scyther-gui-32.ico | Bin 0 -> 4286 bytes .../files/scyther/Images/scyther-gui-64.ico | Bin 0 -> 16958 bytes .../files/scyther/Images/scyther-icon.svg | 222 +++++ .../files/scyther/Images/scyther-splash.png | Bin 0 -> 119951 bytes .../files/scyther/Protocols/Demo/ns3.spdl | 41 + .../scyther/Protocols/Demo/nsl3-broken.spdl | 40 + .../Protocols/Demo/nsl3-updated-both.spdl | 78 ++ .../files/scyther/Protocols/Demo/nsl3.spdl | 38 + .../Protocols/IEEE-WIMAX/pkmv2rsa.spdl | 46 + .../IEEE-WIMAX/pkmv2rsacorrected.spdl | 46 + .../Protocols/IEEE-WIMAX/pkmv2satek.spdl | 63 ++ .../scyther/Protocols/IEEE-WIMAX/pqr.spdl | 84 ++ .../Protocols/IEEE-WIMAX/rsaplussatek.spdl | 74 ++ .../IEEE-WIMAX/rsaplussatekcorrected.spdl | 73 ++ .../files/scyther/Protocols/IKE/Makefile | 11 + .../files/scyther/Protocols/IKE/common.h | 157 +++ .../scyther/Protocols/IKE/ikev1-pk-a1.cpp | 96 ++ .../scyther/Protocols/IKE/ikev1-pk-a1.spdl | 129 +++ .../scyther/Protocols/IKE/ikev1-pk-a12.cpp | 95 ++ .../scyther/Protocols/IKE/ikev1-pk-a12.spdl | 128 +++ .../scyther/Protocols/IKE/ikev1-pk-a2.cpp | 97 ++ .../scyther/Protocols/IKE/ikev1-pk-a2.spdl | 129 +++ .../scyther/Protocols/IKE/ikev1-pk-a22.cpp | 95 ++ .../scyther/Protocols/IKE/ikev1-pk-a22.spdl | 128 +++ .../scyther/Protocols/IKE/ikev1-pk-m.cpp | 103 ++ .../scyther/Protocols/IKE/ikev1-pk-m.spdl | 136 +++ .../scyther/Protocols/IKE/ikev1-pk-m2.cpp | 102 ++ .../scyther/Protocols/IKE/ikev1-pk-m2.spdl | 135 +++ .../scyther/Protocols/IKE/ikev1-pk2-a.cpp | 97 ++ .../scyther/Protocols/IKE/ikev1-pk2-a.spdl | 129 +++ .../scyther/Protocols/IKE/ikev1-pk2-a2.cpp | 97 ++ .../scyther/Protocols/IKE/ikev1-pk2-a2.spdl | 128 +++ .../scyther/Protocols/IKE/ikev1-pk2-m.cpp | 104 ++ .../scyther/Protocols/IKE/ikev1-pk2-m.spdl | 136 +++ .../scyther/Protocols/IKE/ikev1-pk2-m2.cpp | 106 +++ .../scyther/Protocols/IKE/ikev1-pk2-m2.spdl | 136 +++ .../scyther/Protocols/IKE/ikev1-psk-a.cpp | 94 ++ .../scyther/Protocols/IKE/ikev1-psk-a.spdl | 125 +++ .../Protocols/IKE/ikev1-psk-m-perlman.cpp | 101 ++ .../Protocols/IKE/ikev1-psk-m-perlman.spdl | 131 +++ .../scyther/Protocols/IKE/ikev1-psk-m.cpp | 100 ++ .../scyther/Protocols/IKE/ikev1-psk-m.spdl | 130 +++ .../Protocols/IKE/ikev1-quick-noid.cpp | 102 ++ .../Protocols/IKE/ikev1-quick-noid.spdl | 124 +++ .../Protocols/IKE/ikev1-quick-nopfs.cpp | 96 ++ .../Protocols/IKE/ikev1-quick-nopfs.spdl | 118 +++ .../scyther/Protocols/IKE/ikev1-quick.cpp | 70 ++ .../scyther/Protocols/IKE/ikev1-quick.spdl | 91 ++ .../Protocols/IKE/ikev1-sig-a-perlman1.cpp | 99 ++ .../Protocols/IKE/ikev1-sig-a-perlman1.spdl | 130 +++ .../Protocols/IKE/ikev1-sig-a-perlman2.cpp | 99 ++ .../Protocols/IKE/ikev1-sig-a-perlman2.spdl | 130 +++ .../scyther/Protocols/IKE/ikev1-sig-a1.cpp | 98 ++ .../scyther/Protocols/IKE/ikev1-sig-a1.spdl | 130 +++ .../scyther/Protocols/IKE/ikev1-sig-a2.cpp | 99 ++ .../scyther/Protocols/IKE/ikev1-sig-a2.spdl | 130 +++ .../Protocols/IKE/ikev1-sig-m-perlman.cpp | 100 ++ .../Protocols/IKE/ikev1-sig-m-perlman.spdl | 133 +++ .../scyther/Protocols/IKE/ikev1-sig-m.cpp | 102 ++ .../scyther/Protocols/IKE/ikev1-sig-m.spdl | 134 +++ .../Protocols/IKE/ikev2-child-nopfs.cpp | 78 ++ .../Protocols/IKE/ikev2-child-nopfs.spdl | 112 +++ .../scyther/Protocols/IKE/ikev2-child.cpp | 87 ++ .../scyther/Protocols/IKE/ikev2-child.spdl | 121 +++ .../files/scyther/Protocols/IKE/ikev2-eap.cpp | 131 +++ .../scyther/Protocols/IKE/ikev2-eap.spdl | 160 ++++ .../scyther/Protocols/IKE/ikev2-eap2.cpp | 138 +++ .../scyther/Protocols/IKE/ikev2-eap2.spdl | 160 ++++ .../files/scyther/Protocols/IKE/ikev2-mac.cpp | 104 ++ .../scyther/Protocols/IKE/ikev2-mac.spdl | 133 +++ .../scyther/Protocols/IKE/ikev2-mac2.cpp | 104 ++ .../scyther/Protocols/IKE/ikev2-mac2.spdl | 133 +++ .../scyther/Protocols/IKE/ikev2-mactosig.cpp | 104 ++ .../scyther/Protocols/IKE/ikev2-mactosig.spdl | 132 +++ .../scyther/Protocols/IKE/ikev2-mactosig2.cpp | 103 ++ .../Protocols/IKE/ikev2-mactosig2.spdl | 131 +++ .../IKE/ikev2-sig-child-composed.cpp | 138 +++ .../IKE/ikev2-sig-child-composed.spdl | 165 ++++ .../scyther/Protocols/IKE/ikev2-sig-child.cpp | 138 +++ .../Protocols/IKE/ikev2-sig-child.spdl | 165 ++++ .../IKE/ikev2-sig-child2-composed.cpp | 138 +++ .../IKE/ikev2-sig-child2-composed.spdl | 165 ++++ .../Protocols/IKE/ikev2-sig-child2.cpp | 138 +++ .../Protocols/IKE/ikev2-sig-child2.spdl | 165 ++++ .../files/scyther/Protocols/IKE/ikev2-sig.cpp | 103 ++ .../scyther/Protocols/IKE/ikev2-sig.spdl | 132 +++ .../scyther/Protocols/IKE/ikev2-sig2.cpp | 103 ++ .../scyther/Protocols/IKE/ikev2-sig2.spdl | 132 +++ .../scyther/Protocols/IKE/ikev2-sigtomac.cpp | 104 ++ .../scyther/Protocols/IKE/ikev2-sigtomac.spdl | 132 +++ .../scyther/Protocols/IKE/ikev2-sigtomac2.cpp | 104 ++ .../Protocols/IKE/ikev2-sigtomac2.spdl | 132 +++ .../files/scyther/Protocols/IKE/jfki-core.cpp | 54 ++ .../scyther/Protocols/IKE/jfki-core.spdl | 88 ++ .../files/scyther/Protocols/IKE/jfki.cpp | 84 ++ .../files/scyther/Protocols/IKE/jfki.spdl | 118 +++ .../files/scyther/Protocols/IKE/jfkr-core.cpp | 78 ++ .../scyther/Protocols/IKE/jfkr-core.spdl | 112 +++ .../files/scyther/Protocols/IKE/jfkr.cpp | 83 ++ .../files/scyther/Protocols/IKE/jfkr.spdl | 117 +++ .../files/scyther/Protocols/IKE/make-mpa.py | 63 ++ .../scyther/Protocols/IKE/mpa/README.txt | 6 + .../files/scyther/Protocols/IKE/oakley-a.cpp | 60 ++ .../files/scyther/Protocols/IKE/oakley-a.spdl | 91 ++ .../scyther/Protocols/IKE/oakley-alt.cpp | 63 ++ .../scyther/Protocols/IKE/oakley-alt.spdl | 94 ++ .../files/scyther/Protocols/IKE/oakley-c.cpp | 105 ++ .../files/scyther/Protocols/IKE/oakley-c.spdl | 140 +++ .../files/scyther/Protocols/IKE/pp.sh | 21 + .../files/scyther/Protocols/IKE/scanner.py | 800 ++++++++++++++++ .../scyther/Protocols/IKE/skeme-basic.cpp | 61 ++ .../scyther/Protocols/IKE/skeme-basic.spdl | 87 ++ .../files/scyther/Protocols/IKE/skeme-psk.cpp | 82 ++ .../scyther/Protocols/IKE/skeme-psk.spdl | 109 +++ .../scyther/Protocols/IKE/skeme-rekey.cpp | 80 ++ .../scyther/Protocols/IKE/skeme-rekey.spdl | 111 +++ .../files/scyther/Protocols/IKE/sts-mac.cpp | 78 ++ .../files/scyther/Protocols/IKE/sts-mac.spdl | 112 +++ .../files/scyther/Protocols/IKE/sts-main.cpp | 79 ++ .../files/scyther/Protocols/IKE/sts-main.spdl | 114 +++ .../scyther/Protocols/IKE/sts-modified.cpp | 55 ++ .../scyther/Protocols/IKE/sts-modified.spdl | 88 ++ .../files/scyther/Protocols/IKE/verify.sh | 149 +++ .../files/scyther/Protocols/IKE/verify_all.sh | 20 + .../files/scyther/Protocols/ISO-9798/Makefile | 16 + .../scyther/Protocols/ISO-9798/iso25-tag.spdl | 78 ++ .../scyther/Protocols/ISO-9798/iso26-tag.spdl | 95 ++ .../ISO-9798/isoiec-9798-2-1-udkey.spdl | 35 + .../Protocols/ISO-9798/isoiec-9798-2-1.spdl | 55 ++ .../ISO-9798/isoiec-9798-2-2-udkey.spdl | 40 + .../Protocols/ISO-9798/isoiec-9798-2-2.spdl | 59 ++ .../ISO-9798/isoiec-9798-2-3-udkey.spdl | 49 + .../Protocols/ISO-9798/isoiec-9798-2-3.spdl | 67 ++ .../ISO-9798/isoiec-9798-2-4-udkey.spdl | 50 + .../Protocols/ISO-9798/isoiec-9798-2-4.spdl | 88 ++ .../Protocols/ISO-9798/isoiec-9798-2-5.spdl | 93 ++ .../Protocols/ISO-9798/isoiec-9798-2-6.spdl | 90 ++ .../Protocols/ISO-9798/isoiec-9798-3-1.spdl | 33 + .../Protocols/ISO-9798/isoiec-9798-3-2.spdl | 39 + .../Protocols/ISO-9798/isoiec-9798-3-3.spdl | 44 + .../Protocols/ISO-9798/isoiec-9798-3-4.spdl | 46 + .../Protocols/ISO-9798/isoiec-9798-3-5.spdl | 49 + .../Protocols/ISO-9798/isoiec-9798-3-6-1.cpp | 12 + .../Protocols/ISO-9798/isoiec-9798-3-6-1.spdl | 69 ++ .../Protocols/ISO-9798/isoiec-9798-3-6-2.cpp | 12 + .../Protocols/ISO-9798/isoiec-9798-3-6-2.spdl | 69 ++ .../ISO-9798/isoiec-9798-3-6.template | 68 ++ .../Protocols/ISO-9798/isoiec-9798-3-7-1.cpp | 12 + .../Protocols/ISO-9798/isoiec-9798-3-7-1.spdl | 66 ++ .../Protocols/ISO-9798/isoiec-9798-3-7-2.cpp | 12 + .../Protocols/ISO-9798/isoiec-9798-3-7-2.spdl | 68 ++ .../ISO-9798/isoiec-9798-3-7.template | 67 ++ .../ISO-9798/isoiec-9798-4-1-udkey.spdl | 39 + .../Protocols/ISO-9798/isoiec-9798-4-1.spdl | 58 ++ .../ISO-9798/isoiec-9798-4-2-udkey.spdl | 43 + .../Protocols/ISO-9798/isoiec-9798-4-2.spdl | 62 ++ .../ISO-9798/isoiec-9798-4-3-udkey.spdl | 50 + .../Protocols/ISO-9798/isoiec-9798-4-3.spdl | 69 ++ .../ISO-9798/isoiec-9798-4-4-udkey.spdl | 52 + .../Protocols/ISO-9798/isoiec-9798-4-4.spdl | 75 ++ .../Protocols/MultiProtocolAttacks/BKE.spdl | 40 + .../andrew-ban-concrete.spdl | 67 ++ .../MultiProtocolAttacks/andrew-ban.spdl | 52 + .../MultiProtocolAttacks/andrew-lowe-ban.spdl | 57 ++ .../Protocols/MultiProtocolAttacks/boyd.spdl | 56 ++ .../MultiProtocolAttacks/ccitt509-ban3.spdl | 39 + .../denning-sacco-lowe.spdl | 66 ++ .../MultiProtocolAttacks/denning-sacco.spdl | 55 ++ .../MultiProtocolAttacks/gong-nonce-b.spdl | 60 ++ .../MultiProtocolAttacks/gong-nonce.spdl | 57 ++ .../isoiec11770-2-13.spdl | 42 + .../MultiProtocolAttacks/kaochow-v2.spdl | 55 ++ .../MultiProtocolAttacks/kaochow-v3.spdl | 59 ++ .../MultiProtocolAttacks/kaochow.spdl | 55 ++ .../Protocols/MultiProtocolAttacks/ksl.spdl | 75 ++ .../needham-schroeder-sk-amend.spdl | 66 ++ .../needham-schroeder-sk.spdl | 56 ++ .../Protocols/MultiProtocolAttacks/new.txt | 5 + .../Protocols/MultiProtocolAttacks/ns3.spdl | 41 + .../Protocols/MultiProtocolAttacks/nsl3.spdl | 39 + .../MultiProtocolAttacks/otwayrees.spdl | 56 ++ .../Protocols/MultiProtocolAttacks/soph.spdl | 21 + .../MultiProtocolAttacks/splice-as-cj.spdl | 66 ++ .../MultiProtocolAttacks/splice-as-hc.spdl | 61 ++ .../MultiProtocolAttacks/splice-as.spdl | 66 ++ .../Protocols/MultiProtocolAttacks/tmn.spdl | 51 + .../MultiProtocolAttacks/wmf-brutus.spdl | 32 + .../MultiProtocolAttacks/wmf-lowe.spdl | 63 ++ .../Protocols/MultiProtocolAttacks/wmf.spdl | 54 ++ .../MultiProtocolAttacks/woo-lam-pi-1.spdl | 41 + .../MultiProtocolAttacks/woo-lam-pi-2.spdl | 41 + .../MultiProtocolAttacks/woo-lam-pi-3.spdl | 41 + .../MultiProtocolAttacks/woo-lam-pi-f.spdl | 41 + .../MultiProtocolAttacks/woo-lam.spdl | 64 ++ .../yahalom-ban-paulson-modified.spdl | 49 + .../yahalom-ban-paulson.spdl | 47 + .../MultiProtocolAttacks/yahalom-ban.spdl | 55 ++ .../MultiProtocolAttacks/yahalom-lowe.spdl | 53 ++ .../MultiProtocolAttacks/yahalom.spdl | 52 + .../files/scyther/Protocols/NotModelled.txt | 23 + .../Protocols/andrew-ban-concrete.spdl | 67 ++ .../files/scyther/Protocols/andrew-ban.spdl | 54 ++ .../scyther/Protocols/andrew-lowe-ban.spdl | 57 ++ .../files/scyther/Protocols/andrew.spdl | 50 + .../files/scyther/Protocols/ccitt509-1.spdl | 35 + .../files/scyther/Protocols/ccitt509-1c.spdl | 34 + .../files/scyther/Protocols/ccitt509-3.spdl | 45 + .../scyther/Protocols/ccitt509-ban3.spdl | 39 + .../scyther/Protocols/denning-sacco-lowe.spdl | 67 ++ .../scyther/Protocols/denning-sacco.spdl | 53 ++ .../files/scyther/Protocols/kaochow-v2.spdl | 55 ++ .../files/scyther/Protocols/kaochow-v3.spdl | 59 ++ .../files/scyther/Protocols/kaochow.spdl | 55 ++ .../files/scyther/Protocols/ksl-lowe.spdl | 73 ++ .../files/scyther/Protocols/ksl.spdl | 72 ++ .../multi-NSL/heuristics-results.txt | 776 +++++++++++++++ .../Protocols/multi-NSL/mnsl-results.txt | 33 + .../Protocols/multi-NSL/multinsl-generator.py | 345 +++++++ .../Protocols/multi-NSL/test-heuristics.py | 69 ++ .../Protocols/multi-NSL/test-variants.py | 79 ++ .../Protocols/needham-schroeder-lowe.spdl | 53 ++ .../Protocols/needham-schroeder-sk-amend.spdl | 66 ++ .../Protocols/needham-schroeder-sk.spdl | 56 ++ .../scyther/Protocols/needham-schroeder.spdl | 53 ++ .../Protocols/neumannstub-guttman-hwang.spdl | 105 ++ .../Protocols/neumannstub-guttman.spdl | 105 ++ .../scyther/Protocols/neumannstub-hwang.spdl | 71 ++ .../Protocols/neumannstub-keycompromise.spdl | 105 ++ .../files/scyther/Protocols/neumannstub.spdl | 98 ++ .../files/scyther/Protocols/otwayrees.spdl | 56 ++ .../files/scyther/Protocols/smartright.spdl | 46 + .../files/scyther/Protocols/splice-as-cj.spdl | 66 ++ .../files/scyther/Protocols/splice-as-hc.spdl | 61 ++ .../files/scyther/Protocols/splice-as.spdl | 66 ++ .../files/scyther/Protocols/tmn.spdl | 51 + .../files/scyther/Protocols/wmf-lowe.spdl | 63 ++ .../files/scyther/Protocols/wmf.spdl | 54 ++ .../files/scyther/Protocols/woo-lam-pi-1.spdl | 41 + .../files/scyther/Protocols/woo-lam-pi-2.spdl | 41 + .../files/scyther/Protocols/woo-lam-pi-3.spdl | 41 + .../files/scyther/Protocols/woo-lam-pi-f.spdl | 41 + .../files/scyther/Protocols/woo-lam-pi.spdl | 45 + .../files/scyther/Protocols/woo-lam.spdl | 64 ++ .../files/scyther/Protocols/yahalom-ban.spdl | 54 ++ .../files/scyther/Protocols/yahalom-lowe.spdl | 52 + .../scyther/Protocols/yahalom-paulson.spdl | 56 ++ .../files/scyther/Protocols/yahalom.spdl | 52 + Vagrant Files/files/scyther/README.md | 66 ++ .../files/scyther/Scripts/regression-test.py | 91 ++ .../files/scyther/Scripts/regression-test.txt | 64 ++ .../files/scyther/Scripts/scytherview.py | 113 +++ .../files/scyther/Scyther/.gitignore | 3 + Vagrant Files/files/scyther/Scyther/Attack.py | 71 ++ Vagrant Files/files/scyther/Scyther/Claim.py | 197 ++++ Vagrant Files/files/scyther/Scyther/Error.py | 121 +++ .../files/scyther/Scyther/FindDot.py | 129 +++ Vagrant Files/files/scyther/Scyther/Misc.py | 158 +++ .../files/scyther/Scyther/Scyther.py | 648 +++++++++++++ Vagrant Files/files/scyther/Scyther/Term.py | 223 +++++ Vagrant Files/files/scyther/Scyther/Trace.py | 358 +++++++ .../files/scyther/Scyther/XMLReader.py | 357 +++++++ .../files/scyther/Scyther/__init__.py | 29 + Vagrant Files/files/scyther/Time/test.py | 63 ++ Vagrant Files/files/scyther/batcher.sh | 46 + Vagrant Files/files/scyther/combos-book.sh | 11 + Vagrant Files/files/scyther/combos-ike.sh | 8 + Vagrant Files/files/scyther/combos-ikev0.sh | 12 + Vagrant Files/files/scyther/combos-ikev1.sh | 12 + Vagrant Files/files/scyther/combos-ikev2.sh | 13 + Vagrant Files/files/scyther/combos-iso.sh | 11 + .../files/scyther/generate-attack-graphs.py | 131 +++ Vagrant Files/files/scyther/json-scyther.py | 66 ++ Vagrant Files/files/scyther/make-bsub.py | 69 ++ Vagrant Files/files/scyther/mpa.spdl | 79 ++ .../files/scyther/notes-brutus-mpa.txt | 181 ++++ Vagrant Files/files/scyther/ns3.spdl | 47 + Vagrant Files/files/scyther/nsl3-broken.spdl | 40 + Vagrant Files/files/scyther/nsl3.spdl | 47 + Vagrant Files/files/scyther/precompute-ike.sh | 5 + .../files/scyther/progressbarDummy.py | 60 ++ Vagrant Files/files/scyther/scyther-gui.py | 245 +++++ Vagrant Files/files/scyther/scyther-gui.rc | 4 + .../files/scyther/scyther-manual.pdf | Bin 0 -> 365769 bytes Vagrant Files/files/scyther/scyther.py | 57 ++ Vagrant Files/files/scyther/test-delta.py | 181 ++++ Vagrant Files/files/scyther/test-mpa.py | 896 ++++++++++++++++++ Vagrant Files/files/scyther/todo.txt | 29 + Vagrant Files/files/scyther/wiper.sh | 9 + Vagrant Files/files/test folder/guide.txt | 1 + Vagrant Files/scyther.sh | 3 + 311 files changed, 29289 insertions(+) create mode 100644 Vagrant Files/Vagrantfile create mode 100644 Vagrant Files/files/scyther/.gitignore create mode 100644 Vagrant Files/files/scyther/Changelog.txt create mode 100644 Vagrant Files/files/scyther/GNU-General-Public-License.txt create mode 100644 Vagrant Files/files/scyther/Gui/About.py create mode 100644 Vagrant Files/files/scyther/Gui/Attackwindow.py create mode 100644 Vagrant Files/files/scyther/Gui/Editor.py create mode 100644 Vagrant Files/files/scyther/Gui/Error.py create mode 100644 Vagrant Files/files/scyther/Gui/Icon.py create mode 100644 Vagrant Files/files/scyther/Gui/Mainwindow.py create mode 100644 Vagrant Files/files/scyther/Gui/Makeimage.py create mode 100644 Vagrant Files/files/scyther/Gui/Misc.py create mode 100644 Vagrant Files/files/scyther/Gui/Preference.py create mode 100644 Vagrant Files/files/scyther/Gui/Scytherthread.py create mode 100644 Vagrant Files/files/scyther/Gui/Settingswindow.py create mode 100644 Vagrant Files/files/scyther/Gui/Temporary.py create mode 100644 Vagrant Files/files/scyther/Gui/Version.py create mode 100644 Vagrant Files/files/scyther/Gui/__init__.py create mode 100644 Vagrant Files/files/scyther/INSTALL.md create mode 100644 Vagrant Files/files/scyther/INSTALL.txt create mode 100644 Vagrant Files/files/scyther/Images/scyther-gui-16.ico create mode 100644 Vagrant Files/files/scyther/Images/scyther-gui-32.ico create mode 100644 Vagrant Files/files/scyther/Images/scyther-gui-64.ico create mode 100644 Vagrant Files/files/scyther/Images/scyther-icon.svg create mode 100644 Vagrant Files/files/scyther/Images/scyther-splash.png create mode 100644 Vagrant Files/files/scyther/Protocols/Demo/ns3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/Demo/nsl3-broken.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/Demo/nsl3-updated-both.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/Demo/nsl3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2rsa.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2rsacorrected.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2satek.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pqr.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/rsaplussatek.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/rsaplussatekcorrected.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/Makefile create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/common.h create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a1.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a12.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a12.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a22.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a22.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-a.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-a.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m-perlman.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m-perlman.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-noid.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-noid.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-nopfs.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-nopfs.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman1.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a1.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m-perlman.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m-perlman.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-child-nopfs.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-child-nopfs.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-child.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-child.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child-composed.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child-composed.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2-composed.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2-composed.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/jfki-core.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/jfki-core.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/jfki.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/jfki.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/jfkr-core.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/jfkr-core.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/jfkr.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/jfkr.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/make-mpa.py create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/mpa/README.txt create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/oakley-a.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/oakley-a.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/oakley-alt.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/oakley-alt.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/oakley-c.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/oakley-c.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/pp.sh create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/scanner.py create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/skeme-basic.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/skeme-basic.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/skeme-psk.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/skeme-psk.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/skeme-rekey.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/skeme-rekey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/sts-mac.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/sts-mac.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/sts-main.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/sts-main.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/sts-modified.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/sts-modified.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/verify.sh create mode 100644 Vagrant Files/files/scyther/Protocols/IKE/verify_all.sh create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/Makefile create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/iso25-tag.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/iso26-tag.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-1-udkey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-2-udkey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-3-udkey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-4-udkey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-4.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-5.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-6.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-4.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-5.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-1.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6.template create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-1.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-2.cpp create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7.template create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-1-udkey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-2-udkey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-3-udkey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-4-udkey.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-4.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/BKE.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-ban-concrete.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-ban.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-lowe-ban.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/boyd.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ccitt509-ban3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/denning-sacco-lowe.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/denning-sacco.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/gong-nonce-b.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/gong-nonce.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/isoiec11770-2-13.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow-v2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow-v3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ksl.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/needham-schroeder-sk-amend.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/needham-schroeder-sk.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/new.txt create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ns3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/nsl3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/otwayrees.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/soph.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as-cj.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as-hc.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/tmn.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf-brutus.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf-lowe.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-f.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban-paulson-modified.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban-paulson.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-lowe.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/NotModelled.txt create mode 100644 Vagrant Files/files/scyther/Protocols/andrew-ban-concrete.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/andrew-ban.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/andrew-lowe-ban.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/andrew.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ccitt509-1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ccitt509-1c.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ccitt509-3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ccitt509-ban3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/denning-sacco-lowe.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/denning-sacco.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/kaochow-v2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/kaochow-v3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/kaochow.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ksl-lowe.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/ksl.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/multi-NSL/heuristics-results.txt create mode 100644 Vagrant Files/files/scyther/Protocols/multi-NSL/mnsl-results.txt create mode 100644 Vagrant Files/files/scyther/Protocols/multi-NSL/multinsl-generator.py create mode 100644 Vagrant Files/files/scyther/Protocols/multi-NSL/test-heuristics.py create mode 100644 Vagrant Files/files/scyther/Protocols/multi-NSL/test-variants.py create mode 100644 Vagrant Files/files/scyther/Protocols/needham-schroeder-lowe.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/needham-schroeder-sk-amend.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/needham-schroeder-sk.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/needham-schroeder.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/neumannstub-guttman-hwang.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/neumannstub-guttman.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/neumannstub-hwang.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/neumannstub-keycompromise.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/neumannstub.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/otwayrees.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/smartright.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/splice-as-cj.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/splice-as-hc.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/splice-as.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/tmn.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/wmf-lowe.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/wmf.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/woo-lam-pi-1.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/woo-lam-pi-2.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/woo-lam-pi-3.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/woo-lam-pi-f.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/woo-lam-pi.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/woo-lam.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/yahalom-ban.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/yahalom-lowe.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/yahalom-paulson.spdl create mode 100644 Vagrant Files/files/scyther/Protocols/yahalom.spdl create mode 100644 Vagrant Files/files/scyther/README.md create mode 100644 Vagrant Files/files/scyther/Scripts/regression-test.py create mode 100644 Vagrant Files/files/scyther/Scripts/regression-test.txt create mode 100644 Vagrant Files/files/scyther/Scripts/scytherview.py create mode 100644 Vagrant Files/files/scyther/Scyther/.gitignore create mode 100644 Vagrant Files/files/scyther/Scyther/Attack.py create mode 100644 Vagrant Files/files/scyther/Scyther/Claim.py create mode 100644 Vagrant Files/files/scyther/Scyther/Error.py create mode 100644 Vagrant Files/files/scyther/Scyther/FindDot.py create mode 100644 Vagrant Files/files/scyther/Scyther/Misc.py create mode 100644 Vagrant Files/files/scyther/Scyther/Scyther.py create mode 100644 Vagrant Files/files/scyther/Scyther/Term.py create mode 100644 Vagrant Files/files/scyther/Scyther/Trace.py create mode 100644 Vagrant Files/files/scyther/Scyther/XMLReader.py create mode 100644 Vagrant Files/files/scyther/Scyther/__init__.py create mode 100644 Vagrant Files/files/scyther/Time/test.py create mode 100644 Vagrant Files/files/scyther/batcher.sh create mode 100644 Vagrant Files/files/scyther/combos-book.sh create mode 100644 Vagrant Files/files/scyther/combos-ike.sh create mode 100644 Vagrant Files/files/scyther/combos-ikev0.sh create mode 100644 Vagrant Files/files/scyther/combos-ikev1.sh create mode 100644 Vagrant Files/files/scyther/combos-ikev2.sh create mode 100644 Vagrant Files/files/scyther/combos-iso.sh create mode 100644 Vagrant Files/files/scyther/generate-attack-graphs.py create mode 100644 Vagrant Files/files/scyther/json-scyther.py create mode 100644 Vagrant Files/files/scyther/make-bsub.py create mode 100644 Vagrant Files/files/scyther/mpa.spdl create mode 100644 Vagrant Files/files/scyther/notes-brutus-mpa.txt create mode 100644 Vagrant Files/files/scyther/ns3.spdl create mode 100644 Vagrant Files/files/scyther/nsl3-broken.spdl create mode 100644 Vagrant Files/files/scyther/nsl3.spdl create mode 100644 Vagrant Files/files/scyther/precompute-ike.sh create mode 100644 Vagrant Files/files/scyther/progressbarDummy.py create mode 100644 Vagrant Files/files/scyther/scyther-gui.py create mode 100644 Vagrant Files/files/scyther/scyther-gui.rc create mode 100644 Vagrant Files/files/scyther/scyther-manual.pdf create mode 100644 Vagrant Files/files/scyther/scyther.py create mode 100644 Vagrant Files/files/scyther/test-delta.py create mode 100644 Vagrant Files/files/scyther/test-mpa.py create mode 100644 Vagrant Files/files/scyther/todo.txt create mode 100644 Vagrant Files/files/scyther/wiper.sh create mode 100644 Vagrant Files/files/test folder/guide.txt create mode 100644 Vagrant Files/scyther.sh diff --git a/Vagrant Files/Vagrantfile b/Vagrant Files/Vagrantfile new file mode 100644 index 0000000..7283a2b --- /dev/null +++ b/Vagrant Files/Vagrantfile @@ -0,0 +1,73 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure("2") do |config| + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + + # Every Vagrant development environment requires a box. You can search for + # boxes at https://vagrantcloud.com/search. + config.vm.box = "peru/ubuntu-18.04-desktop-amd64" + config.vm.box_version = "20200401.01" + + # Disable automatic box update checking. If you disable this, then + # boxes will only be checked for updates when the user runs + # `vagrant box outdated`. This is not recommended. + # config.vm.box_check_update = false + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:8080" will access port 80 on the guest machine. + # NOTE: This will enable public access to the opened port + # config.vm.network "forwarded_port", guest: 80, host: 8080 + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine and only allow access + # via 127.0.0.1 to disable public access + # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" + + # Create a private network, which allows host-only access to the machine + # using a specific IP. + # config.vm.network "private_network", ip: "192.168.33.10" + + # Create a public network, which generally matched to bridged network. + # Bridged networks make the machine appear as another physical device on + # your network. + # config.vm.network "public_network" + + # Share an additional folder to the guest VM. The first argument is + # the path on the host to the actual folder. The second argument is + # the path on the guest to mount the folder. And the optional third + # argument is a set of non-required options. + # config.vm.synced_folder "../data", "/vagrant_data" + + # Provider-specific configuration so you can fine-tune various + # backing providers for Vagrant. These expose provider-specific options. + # Example for VirtualBox: + # + config.vm.provider "virtualbox" do |vb| + # # Display the VirtualBox GUI when booting the machine + vb.gui = true + vb.memory = "1024" + vb.name = "ubuntudesktopscyther" + vb.customize ["modifyvm", :id, "--vram", "256"] + + end + # + # View the documentation for the provider you are using for more + # information on available options. + + # Enable provisioning with a shell script. Additional provisioners such as + # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the + # documentation for more information about their specific syntax and use. + config.vm.provision "file", source: "files", destination: "/home/vagrant" + config.vm.provision "shell", path: "scyther.sh" + # apt-get update + # apt-get install -y apache2 + # SHELL +end diff --git a/Vagrant Files/files/scyther/.gitignore b/Vagrant Files/files/scyther/.gitignore new file mode 100644 index 0000000..e62e34e --- /dev/null +++ b/Vagrant Files/files/scyther/.gitignore @@ -0,0 +1,4 @@ +*.pyc +progressbar.py +Cache +Cache-OLD diff --git a/Vagrant Files/files/scyther/Changelog.txt b/Vagrant Files/files/scyther/Changelog.txt new file mode 100644 index 0000000..b2af59b --- /dev/null +++ b/Vagrant Files/files/scyther/Changelog.txt @@ -0,0 +1,159 @@ +Scyther changelog +=============================== + +Scyther 1.1.2 +------------------------------- + +Minor: + + * Updated installation instructions. + * Updated 'ffgg' protocol generator for new conventions. + * Windows users recently had to manually set the Graphviz path. Added a + hack to avoid this inconvenience in most (but not all) cases. + * Minor manual update. + +Bug fixes: + + * [Bugfix] Reverted use of shlex. This breaks the "abort backend + thread" functionality again, but it was causing too much trouble on + Windows. + +Scyther 1.1.1 +------------------------------- + +This is mostly a bugfix release. + +New features: + + * [Language] Weakagree and Alive claims now also allow for an optional role + parameter, which can be useful for protocols with more than two roles. + * [Misc] Added Python script to dump attack outputs for large sets of files. + * [Gui] Canceling verification now also kills back-end thread. + +Regression fixes: + + * [Regression-fix] Reintroduced option for specifying alternative PKI. + +Bug fixes: + + * [Bugfix] Fixed rare bug in some cases where hashes were used as symmetric keys. + * [Bugfix] Invoking Scyther scripts from non-standard directories or using symlinks should work consistently now. + * [Bugfix] Improving compatibility with recent versions of Graphviz (>2.26) + +Scyther 1.1 +------------------------------- + +Major new features: + + * [Language] Added support for `macro Term1 = Term2;` definitions, which greatly + simplifies many specifications. + * [Language] Added support for `match(T1,T2);` events in roles, which + can be used for e.g. a straightforward modeling of delayed decryption. + * [Language] Added support for `not match(T1,T2);` events in roles. + This can be useful for, e.g., modeling protocol restrictions (such as + `A != B`). + * [Language] Added support for `option "COMMANDLINE_OPTIONS";` in + specifications. This provides full access to the command-line options + of the Scyther backend to the protocol specifications. An example of + its use is `option "--one-role-per-agent";`. + * [Mac OS X] Dropped support for PPC in Scyther distributions, only + supporting Intel for now. Note that installing from source may still + work fine with a minor tweak to the build script. + +Additional protocol models: + +See <http://www.cs.ox.ac.uk/people/cas.cremers/tools/protocols.html> for a +more high-level overview of selected protocol models. + + * IEEE 802.16e/WIMAX: PKMv2rsa and variants + * IKEv1 and IKEv2 protocol suites + +Other new features: + + * `SCYTHERCACHEDIR` environment variable can be set to override the + internal cache path. + * [Backend] The command-line tool now supports the option + `--one-role-per-agent`. This disallows agents from performing more than + one role in a single trace. This effectively partitions the agents into + role sets, i.e., each role can only be performed by agents from one of + these sets. + * [Documentation] Added the first incomplete version of the new manual. + +There are also various minor bugfixes and installation improvements. + +Scyther 1.0 +------------------------------- + +Major new features: + + * [Language] Support for weak agreement + * [Language] Support for non-injective data agreement through `Commit` + and `Running` signals. + +Bugfixes: + + * Python 2.5 has integrated (c)elementtree into the core. + Unfortunaly, this broke our previous import attempts. This has now + been fixed. + +Scyther 1.0-beta7.1 +------------------------------- + +Bugfixes: + + * Windows Vista fix broke Windows XP support. + +Scyther 1.0-beta7 +------------------------------- + +Bugfixes: + + * Windows Vista causes a number of problems. The biggest problem + is now fixed, which is the bad implementation of the tmpfile() C + function, causing no attack output, for which there is a + workaround now. + +Scyther 1.0-beta6 +------------------------------- + +Major new features: + + * [Gui] Added Mac support (added universal binary) + * [Gui] Switched to Scintilla editor component, providing undo + and line numbering, and highlighting of error lines. + +Other new features: + + * [Backend] Scyther now detects when a recv event cannot match + with a send event. This significantly helps in reducing errors + in the protocol descriptions. + * [Language] Added claim parameter for Reachable claim; + Reachable,R means that role R should be trusted (as well as the + actor), but not any other role. This can be useful for showing + stronger authentication properties of protocols with more than + two parties. + * [Backend] Added '--max-of-role=N' switch (to narrow scenarios) + * [Backend] Added '--scan-claims' switch (allows for retrieving + a list of claims) + * [Scripting] Added 'verifyOne' and 'scanClaims' methods to + Scyther object, to help with singular claim testing. + + Bugfixes: + + * [Scripting] Fixed bug in python interface backend (e.g. with mpa.py) + +Scyther 1.0-beta5 +------------------------------- + + * Change of switch semantics. '--max-attacks=N' now defines the + maximum number of attacks per claim. Previously this was a + global maximum for all claims combined. + * Improved attack graph output. + * added switch '--errors=FILE' to redirect standard error output + to a file. + * Rewrote parts of the gui code for improved stability. + +Scyther 1.0-beta4 +------------------------------- + + * (Changelog starts after the release of Scyther 1.0-beta4) diff --git a/Vagrant Files/files/scyther/GNU-General-Public-License.txt b/Vagrant Files/files/scyther/GNU-General-Public-License.txt new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/Vagrant Files/files/scyther/GNU-General-Public-License.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Vagrant Files/files/scyther/Gui/About.py b/Vagrant Files/files/scyther/Gui/About.py new file mode 100644 index 0000000..b415c55 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/About.py @@ -0,0 +1,137 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import wx.html +import os.path + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ + +import Scyther + +#--------------------------------------------------------------------------- + +""" Globals """ + +basedir = "" + +#--------------------------------------------------------------------------- + +def setBaseDir(mybasedir): + global basedir + + basedir = mybasedir + +#--------------------------------------------------------------------------- + +class AboutScyther(wx.Dialog): + def __init__(self,parent,mybasedir=None): + + from Version import SCYTHER_GUI_VERSION + global basedir + + self.text = ''' +<html> +<body bgcolor="#ffffff"> +<img src="$SPLASH"> +<h5 align="right">Scyther : $VERSION</h5> +<small> + <p> + <b>Scyther</b> is an automatic tool for the verification and + falsification of security protocols. + </p> + <p> + For news and updates visit the Scyther pages at + <a target="_blank" href="http://www.cs.ox.ac.uk/people/cas.cremers/scyther/index.html"> + http://www.cs.ox.ac.uk/people/cas.cremers/scyther/index.html</a> + </p> + <h5>License</h5> + <p> + Scyther : An automatic verifier for security protocols.<br> + Copyright (C) 2007-2013 Cas Cremers + </p> + <p> + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + </p> + <p> + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + </p> + <p> + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + </p> + <h5>Backend version</h5> + <p> + $DETAILS + </p> + <h5>Credits</h5> + <p> + Cas Cremers (Scyther theory, backend, and main GUI + code), Gijs Hollestelle (Python parser for Scyther XML output). + </p> +</small> + ''' + + if mybasedir: + basedir = mybasedir + + # Debugging output of some parameters + + splashdir = os.path.join(basedir,"Images") + splashimage = os.path.join(splashdir,"scyther-splash.png") + details_html = "Base directory: %s<br>\n" % (basedir) + details_html += Scyther.Scyther.GetInfo(html=True) + + self.text = self.text.replace("$SPLASH",splashimage) + self.text = self.text.replace("$DETAILS",details_html) + + # version information + self.text = self.text.replace("$VERSION", SCYTHER_GUI_VERSION) + + wx.Dialog.__init__(self, parent, -1, 'About Scyther', + size=(660,620)) + html = wx.html.HtmlWindow(self) + #if "gtk2" in wx.PlatformInfo: + # html.SetStandardFonts() + html.SetBorders(10) + html.SetPage(self.text) + button = wx.Button(self, wx.ID_OK, "Close window") + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(html, 1, wx.EXPAND|wx.ALL,0) + sizer.Add(button,0,wx.ALIGN_CENTER|wx.ALL,5) + + self.SetSizer(sizer) + self.Layout() + +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Attackwindow.py b/Vagrant Files/files/scyther/Gui/Attackwindow.py new file mode 100644 index 0000000..39b9f06 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Attackwindow.py @@ -0,0 +1,330 @@ +#!/usr/bin/python +from __future__ import division # 2.2+-only +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import os +from Misc import * + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ +import Icon +import Preference +import Error + +#--------------------------------------------------------------------------- +try: + import Image +except ImportError: + pass + +#--------------------------------------------------------------------------- + +class AttackDisplay(wx.ScrolledWindow): + """ + Display an attack (inside a tab or not) + """ + def __init__(self, daddy, parent, attack): + + self.win = daddy + self.attack = attack + + wx.ScrolledWindow.__init__(self,parent,id=-1) + + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Image = wx.StaticBitmap(self, -1, wx.EmptyBitmap(1,1)) + self.box = wx.BoxSizer(wx.VERTICAL) + self.box.Add(self.Image,1,wx.ALIGN_CENTER) + self.hbox = wx.BoxSizer(wx.HORIZONTAL) + self.hbox.Add(self.box,1,wx.ALIGN_CENTER) + self.SetSizer(self.hbox) + + self.original = None + + filename = attack.file + if attack.filetype == "png": + self.original = wx.Image(filename,wx.BITMAP_TYPE_PNG) + elif attack.filetype == "ps": + # depends on PIL lib + try: + self.original = Image.open(filename) + except: + Preference.doNotUsePIL() + raise Error.PILError + else: + print "Unknown file type %s." % (self.filetype) + + # TODO self.Bind(wxSizeEvent + self.update(True) + self.Fit() + + def OnSize(self,event): + self.update(False) + event.Skip() + + def update(self,force=True): + + if not force: + if not self.win.fit: + return + + # This is needed, don't ask me why. + self.SetScrollbars(0,0,0,0,0,0) + + (framewidth,frameheight) = self.GetClientSizeTuple() + (virtualwidth,virtualheight) = (framewidth,frameheight) + + def makefit(width,height): + if self.win.fit: + # determine scaling factors for fitting + wfactor = float(framewidth) / width + hfactor = float(frameheight) / height + + # select smallest factor (so it will fit) + if hfactor < wfactor: + factor = hfactor + else: + factor = wfactor + + # apply scaling factor + width = width * factor + height = height * factor + else: + factor = 1.0 + + return (factor, int(width), int(height)) + + if self.attack.filetype == "png": + bmp = self.original + if not bmp.Ok(): + bmp = wx.EmptyImage(1,1) + else: + (originalwidth,originalheight) = (bmp.GetWidth(), bmp.GetHeight()) + if self.win.fit: + (factor, virtualwidth, virtualheight) = makefit(originalwidth,originalheight) + bmp = self.original.Scale(virtualwidth,virtualheight) + self.Image.SetBitmap(wx.BitmapFromImage(bmp)) + + elif self.attack.filetype == "ps": + pil = self.original.copy() + (originalwidth,originalheight) = pil.size + (factor, virtualwidth, virtualheight) = makefit(originalwidth,originalheight) + # we really only want antialias when it's smaller + if factor < 1.0: + pil.thumbnail((virtualwidth,virtualheight),Image.ANTIALIAS) + else: + pil.thumbnail((virtualwidth,virtualheight)) + + image = wx.EmptyImage(pil.size[0],pil.size[1]) + image.SetData(pil.convert('RGB').tostring()) + self.Image.SetBitmap(image.ConvertToBitmap()) + + else: + print "Unknown file type %s." % (self.attack.filetype) + + self.SetVirtualSize((virtualwidth,virtualheight)) + + #self.box.SetItemMinSize(self.Image.GetContainingSizer()) + self.box.Layout() + + step = 20 + xn = int(virtualwidth // step) + 1 + yn = int(virtualheight // step) + 1 + self.SetScrollbars(step,step,xn,yn,0,0) + + """ + Pop up menu + """ + self.popupmenu = wx.Menu() + item = self.popupmenu.Append(-1,"Export image (.png)") + self.Bind(wx.EVT_MENU, self.OnExportPng, item) + item = self.popupmenu.Append(-1,"Export image (.ps)") + self.Bind(wx.EVT_MENU, self.OnExportPs, item) + item = self.popupmenu.Append(-1,"Export image (.pdf)") + self.Bind(wx.EVT_MENU, self.OnExportPdf, item) + item = self.popupmenu.Append(-1,"Export image (.svg)") + self.Bind(wx.EVT_MENU, self.OnExportSvg, item) + item = self.popupmenu.Append(-1,"Export image (.fig)") + self.Bind(wx.EVT_MENU, self.OnExportFig, item) + item = self.popupmenu.Append(-1,"Export graphviz data (.dot)") + self.Bind(wx.EVT_MENU, self.OnExportDot, item) + + self.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup) + + self.Refresh() + + def OnShowPopup(self, event): + pos = event.GetPosition() + pos = self.Image.ScreenToClient(pos) + self.PopupMenu(self.popupmenu, pos) + + def OnPopupItemSelected(self, event): + item = self.popupmenu.FindItemById(event.GetId()) + text = item.GetText() + wx.MessageBox("You selected item %s" % text) + + def askUserForFilename(self, **dialogOptions): + dialog = wx.FileDialog(self, **dialogOptions) + if dialog.ShowModal() == wx.ID_OK: + res = "%s/%s" % (dialog.GetDirectory(), dialog.GetFilename()) + else: + res = None + dialog.Destroy() + return res + + def saveFileName(self, ext): + (p,r,l) = self.win.claim.triplet() + prefix = "pattern-%s_%s_%s-%s" % (p,r,l,self.attack.id) + suggested = "%s.%s" % (prefix,ext) + res = self.askUserForFilename(style=wx.SAVE, wildcard="*.%s" % (ext), defaultFile = "%s" % (suggested)) + return res + + def exportImage(self, type,ext=None): + if ext == None: + ext = type + res = self.saveFileName(ext) + if res != None: + cmd = "dot -T%s" % (type) + cmdpushwrite(cmd,self.attack.scytherDot,res) + + def OnExportPng(self, event): + self.exportImage("png") + + def OnExportPs(self, event): + self.exportImage("ps") + + def OnExportPdf(self, event): + self.exportImage("pdf") + + def OnExportSvg(self, event): + self.exportImage("svg") + + def OnExportFig(self, event): + self.exportImage("fig") + + def OnExportDot(self, event): + res = self.saveFileName("dot") + if res != None: + fp = open(res,'w') + fp.write(self.attack.scytherDot) + fp.close() + + + + + +#--------------------------------------------------------------------------- + +class AttackWindow(wx.Frame): + def __init__(self,cl): + super(AttackWindow, self).__init__(None, size=(800,800)) + + self.claim = cl + + # TODO maybe fitting defaults should come from Preferences. + # Now, it is default no even if we have PIL, for performance + # reasons. + self.fit = False + + self.CreateInteriorWindowComponents() + + Icon.ScytherIcon(self) + self.SetTitle() + + def SetTitle(self): + + tstr = self.claim.stateName(len(self.claim.attacks),True) + tstr += " for claim %s" % self.claim.id + super(AttackWindow, self).SetTitle(tstr) + + def CreateInteriorWindowComponents(self): + ''' Create "interior" window components. In this case it is the + attack picture. ''' + + sizer = wx.BoxSizer(wx.VERTICAL) + + # Make zoom buttons + if Preference.usePIL(): + buttons = wx.BoxSizer(wx.HORIZONTAL) + bt = wx.ToggleButton(self,-1,"Fit to window") + bt.SetValue(self.fit) + buttons.Add(bt,0) + self.Bind(wx.EVT_TOGGLEBUTTON, self.OnFit, bt) + sizer.Add(buttons, 0, wx.ALIGN_LEFT) + + # Add attacks (possible with tabs) + self.displays=[] + attacks = self.claim.attacks + + n = len(attacks) + if n <= 1: + # Just a single window + dp = AttackDisplay(self, self, attacks[0]) + self.displays.append(dp) + else: + # Multiple tabs + dp = wx.Notebook(self,-1) + for i in range(0,n): + disp = AttackDisplay(self,dp,attacks[i]) + classname = "%s %i" % (self.claim.stateName(1,True),(i+1)) + dp.AddPage(disp, classname) + self.displays.append(disp) + + sizer.Add(dp, 1, wx.EXPAND,1) + + self.SetSizer(sizer) + + def update(self,force=False): + for t in self.displays: + t.update(force) + + def OnFit(self,event): + + if self.fit: + self.fit = False + else: + self.fit = True + self.update(True) + + def OnRealSize(self): + + self.fit = False + self.update(True) + + def OnSize(self): + self.Refresh() + + def OnZoom100(self,evt): + self.fit = False + self.update(True) + self.Refresh() + + def OnZoomFit(self,evt): + self.fit = True + self.update(True) + self.Refresh() + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Editor.py b/Vagrant Files/files/scyther/Gui/Editor.py new file mode 100644 index 0000000..b3e093f --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Editor.py @@ -0,0 +1,195 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import string + +# Use Scintilla editor? +useStc = True # It looks nicer! +#useStc = False # It is sometimes buggy, claims the internet + +# Test Scintilla and if it fails, get rid of it +if useStc: + try: + from wx.stc import * + except: + useStc = False + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ + +#--------------------------------------------------------------------------- + +""" Some constants """ + +#--------------------------------------------------------------------------- + +def justNumbers(txt): + for x in txt: + if not x in string.digits: + return False + return True + +def lineInError(txt): + # First option: square braces + x1 = txt.find("[") + if x1 >= 0: + x2 = txt.find("]") + if x2 > x1: + nrstring = txt[(x1+1):x2] + if justNumbers(nrstring): + return int(nrstring) + # Alternative: ...line x + pref = " line " + i = txt.find(pref) + if i >= 0: + i = i + len(pref) + j = i + while txt[j] in string.digits: + j = j+1 + if j > i: + return int(txt[i:j]) + + return None + +def selectEditor(parent): + """ + Pick an editor (Scintilla or default) and return the object. + """ + if useStc: + return EditorStc(parent) + else: + return EditorNormal(parent) + +#--------------------------------------------------------------------------- + +class Editor(object): + + def __init__(self, parent): + # Empty start + self.SetText("") + self.SetChanged(False) + + def SetText(self): + pass + + def SetErrors(self,errors): + pass + + def GetChanged(self): + """ + Return true if file was changed + """ + return self.savedtext != self.GetText() + + def SetChanged(self,nowchanged=False): + """ + Set changed status + """ + if nowchanged: + self.savedtext = "" + else: + self.SetSaved() + + def SetSaved(self): + self.savedtext = self.GetText() + + def SetOpened(self): + self.SetSaved() + +#--------------------------------------------------------------------------- + +class EditorNormal(Editor): + + def __init__(self, parent): + self.control = wx.TextCtrl(parent, style=wx.TE_MULTILINE) + + # Call parent + Editor.__init__(self,parent) + + def GetText(self): + return self.control.GetValue() + + def SetText(self, txt): + self.control.SetValue(txt) + +#--------------------------------------------------------------------------- + +class EditorStc(Editor): + + def __init__(self, parent): + # Scintilla layout with line numbers + self.control = StyledTextCtrl(parent) + self.control.SetMarginType(1, STC_MARGIN_NUMBER) + self.control.SetMarginWidth(1, 30) + + # Call parent + Editor.__init__(self,parent) + + # Set variable for error style + self.errorstyle = 5 + self.control.StyleSetSpec(self.errorstyle, "fore:#FFFF0000,back:#FF0000") + + def GetText(self): + return self.control.GetText() + + def SetText(self, txt): + self.control.SetText(txt) + + def GetLineCount(self): + """ Currently rather stupid, can probably be done more + efficiently through some Scintilla function. """ + txt = self.GetText().splitlines() + return len(txt) + + def SetErrorLine(self,line): + """ + Currently this is BROKEN for include commands, as no file names + are propagated. To minize the damage, we at least don't try to + highlight non-existing names. In the long run of course + propagation is the only way to handle this. + """ + if line <= self.GetLineCount(): + if line > 0: + line = line - 1 # Start at 0 in stc, but on screen count is 1 + pos = self.control.GetLineIndentPosition(line) + last = self.control.GetLineEndPosition(line) + self.control.StartStyling(pos,31) + self.control.SetStyling(last-pos,self.errorstyle) + + def ClearErrors(self): + self.control.ClearDocumentStyle() + + def SetErrors(self,errors): + if errors: + for el in errors: + nr = lineInError(el) + if nr: + self.SetErrorLine(nr) + else: + self.ClearErrors() + +#--------------------------------------------------------------------------- + diff --git a/Vagrant Files/files/scyther/Gui/Error.py b/Vagrant Files/files/scyther/Gui/Error.py new file mode 100644 index 0000000..6433cf2 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Error.py @@ -0,0 +1,51 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import sys + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ + +#--------------------------------------------------------------------------- + +class PILError (Exception): + pass + +class NoAttackError(Exception): + pass + +#--------------------------------------------------------------------------- + +def ShowAndReturn(text): + title = "Error" + dlg = wx.MessageDialog(None, text, title, wx.ID_OK | wx.ICON_ERROR) + result = dlg.ShowModal() + dlg.Destroy() + +def ShowAndExit(text): + ShowAndReturn(text) + sys.exit() + diff --git a/Vagrant Files/files/scyther/Gui/Icon.py b/Vagrant Files/files/scyther/Gui/Icon.py new file mode 100644 index 0000000..2f4f26f --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Icon.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import os.path +import sys + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ +import Misc + +#--------------------------------------------------------------------------- + +def ScytherIcon(window): + """ Set a nice Scyther icon """ + import os,inspect + + # Determine base directory (taking symbolic links into account) + cmd_file = os.path.realpath(os.path.abspath(inspect.getfile( inspect.currentframe() ))) + basedir = os.path.split(cmd_file)[0] + + path = os.path.join(basedir,"Images") + iconfile = Misc.mypath(os.path.join(path,"scyther-gui-32.ico")) + if os.path.isfile(iconfile): + icon = wx.Icon(iconfile,wx.BITMAP_TYPE_ICO) + window.SetIcon(icon) + + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Mainwindow.py b/Vagrant Files/files/scyther/Gui/Mainwindow.py new file mode 100644 index 0000000..70ce112 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Mainwindow.py @@ -0,0 +1,322 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import os.path + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ +import Settingswindow +import Scytherthread +import Icon +import About +import Editor +import Preference + +#--------------------------------------------------------------------------- + +""" Some constants """ +ID_VERIFY = 100 +ID_AUTOVERIFY = 101 +ID_CHARACTERIZE = 102 +ID_CHECK = 103 + +#--------------------------------------------------------------------------- + +def MainInitOnce(): + result = Preference.usePIL() # Makes sure PIL is tested. + +class MainWindow(wx.Frame): + + def __init__(self, opts, args): + super(MainWindow, self).__init__(None, size=(600,800)) + + self.opts = opts + self.args = args + + self.dirname = os.path.abspath('.') + + MainInitOnce() + + self.filename = 'noname.spdl' + self.filepath = "" + + self.load = False + + # test + if opts.test: + self.filename = 'scythergui-default.spdl' + self.load = True + + # if there is an argument (file), we load it + if len(args) > 0: + filename = args[0] + if filename != '' and os.path.isfile(filename): + (self.dirname,self.filename) = os.path.split(filename) + self.load = True + + Icon.ScytherIcon(self) + + self.CreateInteriorWindowComponents() + self.CreateExteriorWindowComponents() + + aTable = wx.AcceleratorTable([ + (wx.ACCEL_CTRL, ord('Q'), wx.ID_EXIT), + (wx.ACCEL_NORMAL, wx.WXK_F1, + ID_VERIFY), + (wx.ACCEL_NORMAL, wx.WXK_F2, + ID_CHARACTERIZE), + (wx.ACCEL_NORMAL, wx.WXK_F5, + ID_CHECK), + (wx.ACCEL_NORMAL, wx.WXK_F6, + ID_AUTOVERIFY), + ]) + self.SetAcceleratorTable(aTable) + + self.claimlist = [] + self.pnglist = [] + + #self.SetTitle(self.title) + + self.firstCommand() + + def CreateInteriorWindowComponents(self): + ''' Create "interior" window components. In this case it is just a + simple multiline text control. ''' + + ## Make zoom buttons + #sizer = wx.BoxSizer(wx.VERTICAL) + #buttons = wx.BoxSizer(wx.HORIZONTAL) + #bt = wx.Button(self,ID_VERIFY) + #buttons.Add(bt,0) + #self.Bind(wx.EVT_BUTTON, self.OnVerify, bt) + #bt = wx.Button(self,ID_CHARACTERIZE) + #buttons.Add(bt,0) + #self.Bind(wx.EVT_BUTTON, self.OnCharacterize, bt) + #sizer.Add(buttons, 0, wx.ALIGN_LEFT) + + # Top: input + self.top = wx.Notebook(self,-1) + # Editor there + self.editor = Editor.selectEditor(self.top) + + if self.load: + textfile = open(os.path.join(self.dirname, self.filename), 'r') + self.editor.SetText(textfile.read()) + if self.dirname != "": + os.chdir(self.dirname) + textfile.close() + self.editor.SetOpened() + + self.top.AddPage(self.editor.control,"Protocol description") + self.settings = Settingswindow.SettingsWindow(self.top,self) + self.top.AddPage(self.settings,"Settings") + + #sizer.Add(self.top,1,wx.EXPAND,1) + #self.SetSizer(sizer) + + def CreateExteriorWindowComponents(self): + ''' Create "exterior" window components, such as menu and status + bar. ''' + self.CreateMenus() + self.SetTitle() + + def CreateMenu(self, bar, name, list): + + fileMenu = wx.Menu() + for id, label, helpText, handler in list: + if id == None: + fileMenu.AppendSeparator() + else: + item = fileMenu.Append(id, label, helpText) + self.Bind(wx.EVT_MENU, handler, item) + bar.Append(fileMenu, name) # Add the fileMenu to the MenuBar + + + def CreateMenus(self): + menuBar = wx.MenuBar() + self.CreateMenu(menuBar, '&File', [ + (wx.ID_OPEN, '&Open', 'Open a new file', self.OnOpen), + (wx.ID_SAVE, '&Save', 'Save the current file', self.OnSave), + (wx.ID_SAVEAS, 'Save &As', 'Save the file under a different name', + self.OnSaveAs), + (None, None, None, None), + (wx.ID_EXIT, 'E&xit\tCTRL-Q', 'Terminate the program', + self.OnExit)]) + self.CreateMenu(menuBar, '&Verify', + [(ID_VERIFY, '&Verify protocol\tF1','Verify the protocol in the buffer using Scyther', + self.OnVerify) , + (ID_CHARACTERIZE, '&Characterize roles\tF2','TODO' , + self.OnCharacterize) , + (None, None, None, None), + ### Disabled for now (given that it is not reliable enough yet) + #(ID_CHECK, '&Check protocol\tF5','TODO', + # self.OnCheck) , + (ID_AUTOVERIFY, 'Verify &automatic claims\tF6','TODO', + self.OnAutoVerify) + ]) + self.CreateMenu(menuBar, '&Help', + [(wx.ID_ABOUT, '&About', 'Information about this program', + self.OnAbout) ]) + self.SetMenuBar(menuBar) # Add the menuBar to the Frame + + + def SetTitle(self): + # MainWindow.SetTitle overrides wx.Frame.SetTitle, so we have to + # call it using super: + super(MainWindow, self).SetTitle('Scyther: %s'%self.filename) + + # Helper methods: + + def defaultFileDialogOptions(self): + ''' Return a dictionary with file dialog options that can be + used in both the save file dialog as well as in the open + file dialog. ''' + return dict(message='Choose a file', defaultDir=self.dirname, + wildcard='*.spdl') + + def askUserForFilename(self, **dialogOptions): + dialog = wx.FileDialog(self, **dialogOptions) + if dialog.ShowModal() == wx.ID_OK: + userProvidedFilename = True + self.filepath = dialog.GetPath() + (p1,p2) = os.path.split(self.filepath) + self.dirname = p1 + self.filename = p2 + self.SetTitle() # Update the window title with the new filename + else: + userProvidedFilename = False + dialog.Destroy() + return userProvidedFilename + + # Are we dropping a changed file? + + def ConfirmLoss(self,text=None): + """ + Try to drop the current file. If it was changed, try to save + (as) + + Returns true after the user seems to be happy either way, false + if we need to cancel this. + """ + if self.editor.GetChanged(): + # File changed, we need to confirm this + title = "Unsaved changes" + if text: + title = "%s - " + title + txt = "The protocol file '%s' has been modified.\n\n" % (self.filename) + txt = txt + "Do you want to" + txt = txt + " save your changes (Yes)" + txt = txt + " or" + txt = txt + " discard them (No)" + txt = txt + "?" + dialog = wx.MessageDialog(self,txt,title,wx.YES_NO | wx.CANCEL | wx.ICON_EXCLAMATION) + result = dialog.ShowModal() + dialog.Destroy() + if result == wx.ID_NO: + # Drop changes + return True + elif result == wx.ID_YES: + # First save(as)! + if self.OnSaveAs(None): + # Succeeded, we can continue with the operation + return True + else: + # Save did not succeed + return False + else: + # Assume cancel (wx.ID_CANCEL) otherwise + return False + else: + # File was not changed, so we can just proceed + return True + + # Event handlers + + def OnAbout(self, event): + dlg = About.AboutScyther(self) + dlg.ShowModal() + dlg.Destroy() + + def OnExit(self, event): + if self.ConfirmLoss("Exit"): + self.Close() # Close the main window. + return True + return False + + def OnSave(self, event): + textfile = open(os.path.join(self.dirname, self.filename), 'w') + textfile.write(self.editor.GetText()) + textfile.close() + self.editor.SetSaved() + return True + + def OnOpen(self, event): + if self.ConfirmLoss("Open"): + if self.askUserForFilename(style=wx.OPEN, + **self.defaultFileDialogOptions()): + textfile = open(os.path.join(self.dirname, self.filename), 'r') + self.editor.SetText(textfile.read()) + textfile.close() + self.editor.SetOpened() + return True + return False + + def OnSaveAs(self, event): + if self.askUserForFilename(defaultFile=self.filename, style=wx.SAVE, + **self.defaultFileDialogOptions()): + self.OnSave(event) + os.chdir(self.dirname) + return True + return False + + def RunScyther(self, mode): + # Clear errors before verification + self.editor.SetErrors(None) + # Verify spdl + spdl = self.editor.GetText() + s = Scytherthread.ScytherRun(self,mode,spdl,self.editor.SetErrors) + + def OnVerify(self, event): + self.RunScyther("verify") + + def OnAutoVerify(self, event): + self.RunScyther("autoverify") + + def OnCharacterize(self, event): + self.RunScyther("characterize") + + def OnCheck(self, event): + self.RunScyther("check") + + def firstCommand(self): + if self.opts.command: + # Trigger a command automatically + self.Show(True) + self.RunScyther(self.opts.command) + + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Makeimage.py b/Vagrant Files/files/scyther/Gui/Makeimage.py new file mode 100644 index 0000000..220996f --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Makeimage.py @@ -0,0 +1,180 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import os +import sys +from subprocess import Popen, PIPE + +#--------------------------------------------------------------------------- + +""" Import scyther components """ +from Scyther import Misc as MiscScyther +from Scyther import FindDot + +""" Import scyther-gui components """ +import Temporary +import Preference + +#--------------------------------------------------------------------------- +try: + import Image +except ImportError: + pass +#--------------------------------------------------------------------------- + + +def writeGraph(attackthread,txt,fp): + + EDGE = 0 + NODE = 1 + DEFAULT = 2 + ALL = 3 + + def graphLine(txt): + fp.write("\t%s;\n" % (txt)) + + def setAttr(atxt,EdgeNodeDefAll=ALL): + if EdgeNodeDefAll == ALL: + setAttr(atxt,EDGE) + setAttr(atxt,NODE) + setAttr(atxt,DEFAULT) + else: + if EdgeNodeDefAll == EDGE: + edge = "edge" + elif EdgeNodeDefAll == NODE: + edge = "node" + else: + graphLine("%s" % atxt) + return + graphLine("%s [%s]" % (edge,atxt)) + + if sys.platform.startswith("darwin"): + attackthread.fontname = "Helvetica" + elif sys.platform.startswith("win"): + attackthread.fontname = "Courier" + else: + #font = wx.Font(9,wx.SWISS,wx.NORMAL,wx.NORMAL) + #attackthread.fontname = font.GetFaceName() + attackthread.fontname = "\"Helvetica\"" + + # write all graph lines but add layout modifiers + for l in txt.splitlines(): + fp.write(l) + if l.startswith("digraph"): + # Write additional stuff for this graph + # + # [CC][x] This dpi setting messed up quite a bit + #graphLine("dpi=96") + graphLine("rankdir=TB") + #graphLine("nodesep=0.1") + #graphLine("ranksep=0.001") + #graphLine("mindist=0.1") + + # Set fontname + if attackthread.fontname: + fontstring = "fontname=%s" % (attackthread.fontname) + setAttr(fontstring) + + # Stupid Mac <> Graphviz bug fix + if (sys.platform.startswith("mac")) or (sys.platform.startswith("darwin")): + # Note that dot on Mac cannot find the fonts by default, + # and we have to set them accordingly. + os.environ["DOTFONTPATH"]="~/Library/Fonts:/Library/Fonts:/System/Library/Fonts" + + # Select font size + if attackthread.parent and attackthread.parent.mainwin: + fontsize = attackthread.parent.mainwin.settings.fontsize + setAttr("fontsize=%s" % fontsize) + #setAttr("height=\"0.1\"",NODE) + #setAttr("width=\"1.0\"",NODE) + #setAttr("margin=\"0.3,0.03\"",NODE) + + +def makeImageDot(dotdata,attackthread=None): + """ create image for this particular dot data """ + + if Preference.usePIL(): + # If we have the PIL library, we can do postscript! great + # stuff. + type = "ps" + ext = ".ps" + else: + # Ye olde pnge file + type = "png" + ext = ".png" + + # Retrieve dot command path + dotcommand = FindDot.findDot() + + # command to write to temporary file + (fd2,fpname2) = Temporary.tempcleaned(ext) + f = os.fdopen(fd2,'w') + + # Set up command + cmd = "%s -T%s" % (dotcommand,type) + + # execute command + p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE) + + + if attackthread: + writeGraph(attackthread,dotdata,p.stdin) + else: + p.stdin.write(dotdata) + + p.stdin.close() + + for l in p.stdout.read(): + f.write(l) + + p.stdout.close() + f.flush() + f.close() + + return (fpname2, type) + + +def makeImage(attack,attackthread=None): + """ create image for this particular attack """ + + """ This should clearly be a method of 'attack' """ + + (name,type) = makeImageDot(attack.scytherDot,attackthread) + # if this is done, store and report + attack.file = name + attack.filetype = type + + +def testImage(): + """ + We generate a postscript file from a dot file, and see what happens. + """ + + dotdata = "digraph X {\nA->B;\n}\n" + (filename,filetype) = makeImageDot(dotdata) + testimage = Image.open(filename) + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Misc.py b/Vagrant Files/files/scyther/Gui/Misc.py new file mode 100644 index 0000000..f255124 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Misc.py @@ -0,0 +1,90 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Misc.py +# Various helper functions + +#--------------------------------------------------------------------------- + +""" Import externals """ +import os.path +from subprocess import Popen,PIPE + +#--------------------------------------------------------------------------- + +def confirm(question): + answer = '' + while answer not in ('y','n'): + print question, + answer = raw_input().lower() + return answer == 'y' + +def exists(func,list): + return len(filter(func,list)) > 0 + +def forall(func,list): + return len(filter(func,list)) == len(list) + +def uniq(li): + result = [] + for elem in li: + if (not elem in result): + result.append(elem) + return result + +# Return a sorted copy of a list +def sorted(li): + result = li[:] + result.sort() + return result + + +# path +def mypath(file): + """ Construct a file path relative to the scyther-gui main directory + """ + import os, inspect + + # Determine base directory (taking symbolic links into account) + cmd_file = os.path.realpath(os.path.abspath(inspect.getfile( inspect.currentframe() ))) + basedir = os.path.split(cmd_file)[0] + return os.path.join(basedir,file) + +# commands: push data in, get fp.write out +def cmdpushwrite(cmd,data,fname): + """ + Feed stdin data to cmd, write the output to a freshly created file + 'fname'. The file is flushed and closed at the end. + """ + fp = open(fname,'w') + # execute command + p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE) + (cin,cout) = (p.stdin, p.stdout) + + cin.write(data) + cin.close() + for l in cout.read(): + fp.write(l) + cout.close() + fp.flush() + fp.close() + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Preference.py b/Vagrant Files/files/scyther/Gui/Preference.py new file mode 100644 index 0000000..90db531 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Preference.py @@ -0,0 +1,240 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +""" + Preferences window and logic for saving and loading such things. + Thus, some default things can be set here. + + init loads stuff + save save the settings after some changes + set(k,v) + get(k) + + Currently used: + + match + maxruns + scytheroptions + bindir where the scyther executables reside + splashscreen 0/1 +""" + +#--------------------------------------------------------------------------- + +""" Import externals """ + +import wx +import os.path +import sys +from time import localtime,strftime + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ +import Makeimage + +#--------------------------------------------------------------------------- + +""" Globals """ +# Do we have the Python Imaging library? +havePIL = True +testPILOkay = None +try: + import Image +except ImportError: + havePIL = False + +""" Locations of preferences. The last one is supposedly writable. """ +prefname = "scythergui-config" +preflocs = [] + +#--------------------------------------------------------------------------- + +def usePIL(): + """ + Determine whether or not we should use the PIL library + """ + global havePIL, testPILOkay + + if not havePIL: + return False + + # Only if we have it, and it is windows. + if not sys.platform.startswith("lin"): + return False + + # Seems fine. But did we already test it? + if testPILOkay != None: + return testPILOkay + + # Test the usage + testPILOkay = True + testPILOkay = testPIL() + return testPILOkay + +def doNotUsePIL(): + """ + Disable + """ + global havePIL + + havePIL = False + + +def testPIL(): + """ + Test whether PIL works as we want it. + + We generate a postscript file from a dot file, and see what happens. + """ + + # depends on PIL lib + okay = True + try: + Makeimage.testImage() + # PIL seems fine + except: + # PIL broke + doNotUsePIL() + okay = False + + return okay + + +#--------------------------------------------------------------------------- + +class Preferences(dict): + + def setDict(self,d): + """ + Copy dict into self. + """ + for x in d.keys(): + self[x] = d[x] + + def parse(self,line): + line = line.strip() + + """ Skip comments """ + if not line.startswith("#"): + split = line.find("=") + if split != -1: + key = line[:split].strip() + data = line[(split+1):] + self[key] = data.decode("string_escape") + #print "Read %s=%s" % (key,self[key]) + + def load(self,file=""): + if file == None: + self["test1"] = "Dit is met een ' en een \", en dan\nde eerste dinges" + self["test2"] = "En dit de tweede" + elif file == "": + """ + Test default locations + """ + for f in preflocs: + self.load(os.path.join(f,prefname)) + + else: + """ + Read this file + """ + if os.path.isfile(file): + fp = open(file,"r") + for l in fp.readlines(): + self.parse(l) + fp.close() + + def show(self): + print "Preferences:" + for k in self.keys(): + print "%s=%s" % (k, self[k]) + + def save(self): + + print "Saving preferences" + prefpath = preflocs[-1] + if not os.access(prefpath,os.W_OK): + os.makedirs(prefpath) + savename = os.path.join(prefpath,prefname) + fp = open(savename,"w") + + fp.write("# Scyther-gui configuration file.\n#\n") + date = strftime("%c",localtime()) + fp.write("# Last written on %s\n" % (date)) + fp.write("# Do not edit - any changes will be overwritten by Scyther-gui\n\n") + + l = list(self.keys()) + l.sort() + for k in l: + fp.write("%s=%s\n" % (k, self[k].encode("string_escape"))) + + fp.close() + +def init(): + """ + Load the preferences from a file, if possible + """ + global prefs,preflocs + + sp = wx.StandardPaths.Get() + confdir = sp.GetConfigDir() + confdir += "/scyther" + #print confdir + userconfdir = sp.GetUserConfigDir() + userconfdir += "/" + if sys.platform.startswith("lin"): + userconfdir += "." + userconfdir += "scyther" + #print userconfdir + + preflocs = [confdir,userconfdir] + + prefs = Preferences() + prefs.load("") + + +def get(key,alt=None): + global prefs + + if key in prefs.keys(): + return prefs[key] + else: + return alt + +def getkeys(): + global prefs + + return prefs.keys() + +def set(key,value): + global prefs + + prefs[key]=value + return + +def save(): + global prefs + + prefs.save() + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Scytherthread.py b/Vagrant Files/files/scyther/Gui/Scytherthread.py new file mode 100644 index 0000000..2cd5d1a --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Scytherthread.py @@ -0,0 +1,543 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import threading + +#--------------------------------------------------------------------------- + +""" Import scyther components """ +import Scyther.Scyther +import Scyther.Error +from Scyther.Misc import * + +""" Import scyther-gui components """ +import Preference +import Attackwindow +import Icon +import Error +import Makeimage + +#--------------------------------------------------------------------------- +if Preference.havePIL: + import Image +#--------------------------------------------------------------------------- + +class ScytherThread(threading.Thread): + """ + Apply Scyther algorithm to input and retrieve results + """ + + # Override Thread's __init__ method to accept the parameters needed: + def __init__ ( self, spdl, options="", callback=None, mode=None ): + + self.spdl = spdl + self.options = options + self.callback = callback + self.mode = mode + self.popenList = [] + threading.Thread.__init__ ( self ) + + def storePopen(self,p): + self.popenList.append(p) + + def cleanExit(self): + # Cleanup of spawned processes + for index,p in enumerate(self.popenList): + try: + p.kill() + except: + pass + self.popenList = [] + + def run(self): + + (scyther, claims, summary) = self.claimResults() + + # Results are done (claimstatus can be reported) + if self.callback: + wx.CallAfter(self.callback, scyther, claims, summary) + + def claimFixViewOne(self,claims): + """ + This is a stupid hack as long as switches.useAttackBuffer in + Scyther C code is false. It is currently false because Windows + VISTA screwed up the standard C function tmpfile() (It's in a + directory to which normal users cannot write...) + """ + # TODO Notice the stupid default setting too ('2') which is + # needed here. This really needs cleanup. + if int(Preference.get('prune','2')) != 0: + if claims: + for cl in claims: + if len(cl.attacks) > 1: + # Fix it such that by default, only the best attack is + # shown, unless we are in characterize or check mode + # TODO [X] [CC] make switch-dependant. + if not self.mode in ["characterize","check"]: + cl.attacks = [cl.attacks[-1]] + """ Cutting invalidates exactness of attack/behaviour counts """ + cl.complete = False + + return claims + + def claimResults(self): + """ Convert spdl to result (using Scyther) + """ + + scyther = Scyther.Scyther.Scyther() + + scyther.options = self.options + scyther.setInput(self.spdl) + + # verification start + try: + claims = scyther.verify(storePopen=self.storePopen) + except Scyther.Error.ScytherError, el: + claims = None + pass + + summary = str(scyther) + + claims = self.claimFixViewOne(claims) + + return (scyther, claims, summary) + +#--------------------------------------------------------------------------- + +class AttackThread(threading.Thread): + + """ This is a thread because it computes images from stuff in the + background """ + + # Override Thread's __init__ method to accept the parameters needed: + def __init__ ( self, parent, resultwin, callbackclaim=None,callbackattack=None,callbackdone=None ): + + self.parent = parent + self.resultwin = resultwin + self.callbackclaim = callbackclaim + self.callbackattack = callbackattack + self.callbackdone = callbackdone + self.totalattacks = 0 + for cl in self.parent.claims: + for attack in cl.attacks: + self.totalattacks += 1 + + threading.Thread.__init__ ( self ) + + def run(self): + + # create the images in the background + # when the images of a claim are done, callback is called with + # the claim + self.makeImages() + + def makeImages(self): + """ create images """ + + done = 0 + for cl in self.parent.claims: + for attack in cl.attacks: + Makeimage.makeImage(attack,self) + done += 1 + if self.callbackattack: + wx.CallAfter(self.callbackattack,attack,self.totalattacks,done) + if self.callbackclaim: + wx.CallAfter(self.callbackclaim,cl) + if self.callbackdone: + wx.CallAfter(self.callbackdone) + + +#--------------------------------------------------------------------------- + +class VerificationWindow(wx.Dialog): + def __init__( + self, parent, title, pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.DEFAULT_DIALOG_STYLE + ): + + wx.Dialog.__init__(self,parent,-1,title,pos,size,style) + + sizer = wx.BoxSizer(wx.VERTICAL) + + label = wx.StaticText(self, -1, "Verifying protocol description") + sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) + + line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) + sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5) + + btnsizer = wx.StdDialogButtonSizer() + + btn = wx.Button(self, wx.ID_CANCEL) + btnsizer.AddButton(btn) + btnsizer.Realize() + + sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.ALIGN_CENTER, 5) + + self.SetSizer(sizer) + sizer.Fit(self) + + self.Center() + self.Show(True) + +#--------------------------------------------------------------------------- + +class ErrorWindow(wx.Dialog): + def __init__( + self, parent, title, pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.DEFAULT_DIALOG_STYLE,errors=[] + ): + + wx.Dialog.__init__(self,parent,-1,title,pos,size,style) + + sizer = wx.BoxSizer(wx.VERTICAL) + + label = wx.StaticText(self, -1, "Errors") + sizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5) + + line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) + sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5) + + etxt = "" + prefix = "error: " + for er in errors: + if er.startswith(prefix): + er = er[len(prefix):] + etxt = etxt + "%s\n" % (er) + + label = wx.StaticText(self, -1, etxt) + sizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5) + + line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) + sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5) + + btnsizer = wx.StdDialogButtonSizer() + + btn = wx.Button(self, wx.ID_OK) + btnsizer.AddButton(btn) + btnsizer.Realize() + + sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.ALIGN_CENTER, 5) + + self.SetSizer(sizer) + sizer.Fit(self) + +#--------------------------------------------------------------------------- + +class ResultWindow(wx.Frame): + + """ + Displays the claims status and contains buttons to show the actual + attack graphs + """ + + def __init__( + self, parent, parentwindow, title, pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.DEFAULT_DIALOG_STYLE + ): + + wx.Frame.__init__(self,parentwindow,-1,title,pos,size,style) + + Icon.ScytherIcon(self) + + self.parent = parent + self.thread = None + self.Bind(wx.EVT_CLOSE, self.onCloseWindow) + + self.CreateStatusBar() + self.BuildTable() + + def onViewButton(self,evt): + btn = evt.GetEventObject() + try: + w = Attackwindow.AttackWindow(btn.claim) + w.Show(True) + except Error.PILError: + Error.ShowAndReturn("Problem with PIL imaging library: disabled zooming. Please retry to verify the protocol again.") + self.onCloseWindow(None) + + def onCloseWindow(self,evt): + """ TODO we should kill self.thread """ + + # Clean up + self.parent.claims = None + + self.Destroy() + + def BuildTable(self): + # Now continue with the normal construction of the dialog + # contents + + # For these claims... + claims = self.parent.claims + + # set up grid + self.grid = grid = wx.GridBagSizer(0,0) + #self.grid = grid = wx.GridBagSizer(7,1+len(claims)) + + def titlebar(x,title,width=1): + txt = wx.StaticText(self,-1,title) + font = wx.Font(14,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD) + txt.SetFont(font) + grid.Add(txt,(0,x),(1,width),wx.ALL,10) + + titlebar(0,"Claim",4) + titlebar(4,"Status",2) + titlebar(6,"Comments",1) + + self.lastprot = None + self.lastrole = None + views = 0 + for index in range(0,len(claims)): + views += self.BuildClaim(grid,claims[index],index+1) + + if views > 0: + titlebar(7,"Patterns",1) + + self.SetSizer(grid) + self.Fit() + + def BuildClaim(self,grid,cl,ypos): + # a support function + def addtxt(txt,column): + txt = txt.replace("-","_") # Strange fix for wx.StaticText as it cuts off the display. + grid.Add(wx.StaticText(self,-1,txt),(ypos,column),(1,1),wx.ALIGN_CENTER_VERTICAL|wx.ALL,10) + + n = len(cl.attacks) + xpos = 0 + + # protocol, role, label + prot = str(cl.protocol) + showP = False + showR = False + if prot != self.lastprot: + self.lastprot = prot + showP = True + showR = True + role = str(cl.role) + if role != self.lastrole: + self.lastrole = role + showR = True + if showP: + addtxt(prot,xpos) + if showR: + addtxt(role,xpos+1) + xpos += 2 + + # claim id + addtxt(str(cl.id),xpos) + xpos += 1 + + # claim parameters + claimdetails = str(cl.claimtype) + if cl.parameter: + claimdetails += " %s" % (cl.parameter) + # Cut off if very very long + if len(claimdetails) > 50: + claimdetails = claimdetails[:50] + "..." + addtxt(claimdetails + " ",xpos) + xpos += 1 + + # button for ok/fail + if None: + # old style buttons (but they looked ugly on windows) + tsize = (16,16) + if cl.okay: + bmp = wx.ArtProvider_GetBitmap(wx.ART_TICK_MARK,wx.ART_CMN_DIALOG,tsize) + else: + bmp = wx.ArtProvider_GetBitmap(wx.ART_CROSS_MARK,wx.ART_CMN_DIALOG,tsize) + if not bmp.Ok(): + bmp = wx.EmptyBitmap(tsize) + bmpfield = wx.StaticBitmap(self,-1,bmp) + grid.Add(bmpfield,(ypos,xpos),(1,1),wx.ALIGN_CENTER_VERTICAL|wx.ALL,10) + else: + # new style text control Ok/Fail + rankc = cl.getColour() + rankt = cl.getOkay() + txt = wx.StaticText(self,-1,rankt) + font = wx.Font(11,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD) + txt.SetFont(font) + txt.SetForegroundColour(rankc) + grid.Add(txt,(ypos,xpos),(1,1),wx.ALL,10) + xpos += 1 + + # verified? + vt = cl.getVerified() + if vt: + addtxt(vt,xpos) + xpos += 1 + + # remark something + addtxt(cl.getComment(),xpos) + xpos += 1 + + # add view button (enabled later if needed) + if n > 0: + cl.button = wx.Button(self,-1,"%i %s" % (n,cl.stateName(n))) + cl.button.claim = cl + grid.Add(cl.button,(ypos,xpos),(1,1),wx.ALIGN_CENTER_VERTICAL|wx.ALL,5) + cl.button.Disable() + if n > 0: + # Aha, something to show + self.Bind(wx.EVT_BUTTON, self.onViewButton,cl.button) + else: + cl.button = None + xpos += 1 + + # Return 1 if there is a view possible + if n > 0: + return 1 + else: + return 0 + + +#--------------------------------------------------------------------------- + +class ScytherRun(object): + + def __init__(self,mainwin,mode,spdl,errorcallback=None): + + self.mainwin = mainwin + self.mode = mode + self.spdl = spdl + self.verified = False + self.options = mainwin.settings.ScytherArguments(mode) + self.errorcallback=errorcallback + self.SThread = None + + self.main() + + def closer(self,ev): + # Triggered when the window is closed/verification cancelled + t = self.SThread + if t != None: + self.SThread = None + t.cleanExit() + try: + self.verifywin.Destroy() + except: + pass + self.verifywin = None + ev.Skip() + + def main(self): + """ + Start process + """ + + title = "Running Scyther %s process" % self.mode + # start the window and show until something happens + # if it terminates, this is a cancel, and should also kill the thread. (what happens to a spawned Scyther in that case?) + # if the thread terminames, it should close the window normally, and we end up here as well. + #val = self.verifywin.ShowModal() + self.verifywin = VerificationWindow(self.mainwin,title) + + # Check sanity of Scyther thing here (as opposed to the thread) + # which makes error reporting somewhat easier + try: + Scyther.Scyther.Check() + except Scyther.Error.BinaryError, e: + # e.file is the supposed location of the binary + text = "Could not find Scyther binary at\n%s" % (e.file) + Error.ShowAndExit(text) + + # start the thread + self.verifywin.SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) + self.verifywin.Bind(wx.EVT_CLOSE, self.closer) + self.verifywin.Bind(wx.EVT_WINDOW_DESTROY, self.closer) + self.verifywin.Bind(wx.EVT_BUTTON, self.closer, id=wx.ID_CANCEL) + + self.SThread = ScytherThread(self.spdl, self.options, self.verificationDone, self.mode) + self.SThread.start() + + # after verification, we proceed to the callback below... + + def verificationDone(self, scyther, claims, summary): + """ + This is where we end up after a callback from the thread, stating that verification succeeded. + """ + + if self.verifywin == None: + return + + self.scyther = scyther + self.claims = claims + self.summary = summary + + self.verified = True + self.verifywin.Close() + + # Process the claims + if self.scyther.errorcount == 0: + self.verificationOkay() + else: + self.verificationErrors() + + def verificationOkay(self): + + # Great, we verified stuff, progress to the claim report + title = "Scyther results : %s" % self.mode + self.resultwin = resultwin = ResultWindow(self,self.mainwin,title) + + def attackDone(attack,total,done): + if resultwin: + txt = "Generating attack graphs (%i of %i done)." % (done,total) + resultwin.SetStatusText(txt) + #resultwin.Refresh() + + def claimDone(claim): + if resultwin: + if claim.button and len(claim.attacks) > 0: + claim.button.Enable() + + def allDone(): + if resultwin: + resultwin.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) + resultwin.SetStatusText("Done.") + + resultwin.Center() + resultwin.Show(True) + resultwin.SetCursor(wx.StockCursor(wx.CURSOR_ARROWWAIT)) + + wx.Yield() + + t = AttackThread(self,resultwin,claimDone,attackDone,allDone) + t.start() + + resultwin.thread = t + + def verificationErrors(self): + """ + Verification process generated errors. Show them. + """ + + if self.errorcallback: + self.errorcallback(self.scyther.errors) + title = "Scyther errors : %s" % self.mode + errorwin = ErrorWindow(self.mainwin,title,errors=self.scyther.errors) + errorwin.Center() + val = errorwin.ShowModal() + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Settingswindow.py b/Vagrant Files/files/scyther/Gui/Settingswindow.py new file mode 100644 index 0000000..5bc5fa9 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Settingswindow.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import wx +import sys + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ +import Preference +import Scyther.Claim as Claim + +#--------------------------------------------------------------------------- + +class MyGrid(wx.GridBagSizer): + + def __init__(self,parent): + wx.GridBagSizer.__init__(self,hgap=5, vgap=5) + self.ypos = 0 + self.parent = parent + + def stepAdd(self,ctrl,txt): + self.Add(txt,(self.ypos,0),flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) + self.Add(ctrl,(self.ypos,1),flag=wx.ALIGN_LEFT) + self.ypos += 1 + + def lineAdd(self): + return + line = wx.StaticLine(self.parent,-1) + # Currently it is not expanded, and thus invisible. + self.Add(line,pos=(self.ypos,0),span=(1,2),flag=wx.TOP|wx.BOTTOM) + self.ypos += 1 + + def titleAdd(self,title,firstLine=True): + if firstLine: + self.lineAdd() + self.ypos += 1 + txt = wx.StaticText(self.parent,-1,title) + font = wx.Font(12,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD) + txt.SetFont(font) + self.Add(txt,pos=(self.ypos,0),span=(1,2),flag=wx.ALIGN_LEFT) + self.ypos += 1 + self.lineAdd() + +#--------------------------------------------------------------------------- + +class SettingsWindow(wx.Panel): + + def __init__(self,parent,daddy): + wx.Panel.__init__(self,parent,-1) + self.win = daddy + + # layout the stuff + grid = MyGrid(self) + + ### Parameters + grid.titleAdd("Verification parameters",False) + + # Bound on the number of runs + self.maxruns = int(Preference.get('maxruns','5')) + txt = wx.StaticText(self,-1,"Maximum number of runs\n(0 disables bound)") + ctrl = wx.SpinCtrl(self, -1, "",style=wx.RIGHT) + ctrl.SetRange(0,100) + ctrl.SetValue(self.maxruns) + self.Bind(wx.EVT_SPINCTRL,self.EvtRuns,ctrl) + grid.stepAdd(ctrl,txt) + + # Matchin options + self.match = int(Preference.get('match','0')) + claimoptions = ['typed matching','find basic type flaws','find all type flaws'] + r2 = wx.StaticText(self,-1,"Matching type") + l2 = self.ch = wx.Choice(self,-1,choices=claimoptions) + l2.SetSelection(self.match) + self.Bind(wx.EVT_CHOICE,self.EvtMatch,l2) + grid.stepAdd(l2,r2) + + ### MISC expert stuff + grid.titleAdd("Advanced parameters") + + # Continue after finding the first attack + self.prune = int(Preference.get('prune','2')) + claimoptions = ['Find all attacks','Find first attack','Find best attack'] + r8 = wx.StaticText(self,-1,"Search pruning") + l8 = self.ch = wx.Choice(self,-1,choices=claimoptions) + l8.SetSelection(self.prune) + self.Bind(wx.EVT_CHOICE,self.EvtPrune,l8) + grid.stepAdd(l8,r8) + + # Bound on the number of patterns + self.maxattacks = int(Preference.get('maxattacks','10')) + r9 = wx.StaticText(self,-1,"Maximum number of patterns\nper claim") + l9 = wx.SpinCtrl(self, -1, "",style=wx.RIGHT) + l9.SetRange(0,100) + l9.SetValue(self.maxattacks) + self.Bind(wx.EVT_SPINCTRL,self.EvtMaxAttacks,l9) + grid.stepAdd(l9,r9) + + self.misc = Preference.get('scytheroptions','') + r10 = wx.StaticText(self,-1,"Additional backend parameters") + l10 = wx.TextCtrl(self,-1,self.misc,size=(200,-1)) + self.Bind(wx.EVT_TEXT,self.EvtMisc,l10) + grid.stepAdd(l10,r10) + + ### Graph output stuff + grid.titleAdd("Graph output parameters") + + # Bound on the number of classes/attacks + if sys.platform.startswith("lin"): + defsize = 14 + else: + defsize = 11 + self.fontsize = int(Preference.get('fontsize',defsize)) + txt = wx.StaticText(self,-1,"Attack graph font size\n(in points)") + ctrl = wx.SpinCtrl(self, -1, "",style=wx.RIGHT) + ctrl.SetRange(6,32) + ctrl.SetValue(self.fontsize) + self.Bind(wx.EVT_SPINCTRL,self.EvtFontsize,ctrl) + grid.stepAdd(ctrl,txt) + + ### Combine + grid.lineAdd() + self.SetSizer(grid) + self.SetAutoLayout(True) + + def EvtMatch(self,evt): + self.match = evt.GetInt() + + def EvtRuns(self,evt): + self.maxruns = evt.GetInt() + + def EvtFontsize(self,evt): + self.fontsize = evt.GetInt() + + def EvtPrune(self,evt): + self.prune = evt.GetInt() + Preference.set('prune',self.prune) + + def EvtMaxAttacks(self,evt): + self.maxattacks = evt.GetInt() + + def EvtMisc(self,evt): + self.misc = evt.GetString() + + def ScytherArguments(self,mode): + """ Note: constructed strings should have a space at the end to + correctly separate the options. + """ + + tstr = "" + + # Number of runs + tstr += "--max-runs=%s " % (str(self.maxruns)) + # Matching type + tstr += "--match=%s " % (str(self.match)) + # Prune (has to go BEFORE max attacks) + tstr += "--prune=%s" % (str(self.prune)) + # Max attacks/classes + if self.maxattacks != 0: + tstr += "--max-attacks=%s " % (str(self.maxattacks)) + + # Verification type + if mode == "check": + tstr += "--check " + elif mode == "autoverify": + tstr += "--auto-claims " + elif mode == "characterize": + tstr += "--state-space " + + # Anything else? + if self.misc != "": + tstr += " " + self.misc + " " + + return str(tstr) # turn it into a str (might have been unicode weirdness) + +#--------------------------------------------------------------------------- diff --git a/Vagrant Files/files/scyther/Gui/Temporary.py b/Vagrant Files/files/scyther/Gui/Temporary.py new file mode 100644 index 0000000..61c2466 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Temporary.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- + +""" Import externals """ +import os +import tempfile +import atexit + +#--------------------------------------------------------------------------- + +""" Local thing (can be done in numerous nicer ways) """ +tempfiles = [] + +#--------------------------------------------------------------------------- + +def tempremove(tuple): + (fd,fpname) = tuple + #os.close(fd) + os.remove(fpname) + +def cleanupshop(): + global tempfiles + + for tuple in tempfiles: + tempremove(tuple) + +def tempcleaned(post=""): + global tempfiles + + tuple = tempfile.mkstemp(post,"scyther_") + tempfiles.append(tuple) + return tuple + +def tempcleanearly(tuple): + global tempfiles + + tempfiles.remove(tuple) + tempremove(tuple) + +atexit.register(cleanupshop) + + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Gui/Version.py b/Vagrant Files/files/scyther/Gui/Version.py new file mode 100644 index 0000000..d941e4b --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/Version.py @@ -0,0 +1 @@ +SCYTHER_GUI_VERSION = "v1.1.3" diff --git a/Vagrant Files/files/scyther/Gui/__init__.py b/Vagrant Files/files/scyther/Gui/__init__.py new file mode 100644 index 0000000..6995b43 --- /dev/null +++ b/Vagrant Files/files/scyther/Gui/__init__.py @@ -0,0 +1,19 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + diff --git a/Vagrant Files/files/scyther/INSTALL.md b/Vagrant Files/files/scyther/INSTALL.md new file mode 100644 index 0000000..67f772c --- /dev/null +++ b/Vagrant Files/files/scyther/INSTALL.md @@ -0,0 +1,96 @@ +Installation and usage of the Scyther tool +========================================== + +Download +-------- + +Downloads of binary archives of Scyther for all main platforms can be +found at http://users.ox.ac.uk/~coml0529/scyther/index.html + +Requirements +------------ + +To be able to use all of Scyther's features, the following three +dependencies are needed. If you only require the back-end tool (used +from the command line) then you need only the first. + +1. ### The GraphViz library ### + + This library is used by the Scyther tool to draw graphs. It can be + freely downloaded from: + + http://www.graphviz.org/ + + Download the latest stable release and install it. + + +2. ### Python ### + + Stable releases of the Python interpreter are available from: + + http://www.python.org/download/ + + Scyther does not support Python 3. You are therefore recommended to + choose the latest production release of Python 2, e.g., Python 2.7. + + * **Mac OS X** + + If the package yields an error when you try to install it, + please use the following, in the directory where you downloaded + it: + + ``` + $ sudo installer -pkg graphviz-2.34.0.pkg -target / + ``` + + +3. ### wxPython libraries ### + + The GUI user interface uses the wxPython libraries. + + http://www.wxpython.org/download.php + + There are many different wxPython packages. You should choose a 32-bit + package that matches your Python version (e.g., 2.7). It is + recommended to select the unicode version from the stable releases. + + As of writing (May 2013) the following links lead to the appropriate + wxPython packages for Python 2.7: + + * **Windows** + + http://downloads.sourceforge.net/wxpython/wxPython2.8-win32-unicode-2.8.12.1-py27.exe + + * **Mac OS X** + + http://downloads.sourceforge.net/wxpython/wxPython2.8-osx-unicode-2.8.12.1-universal-py2.7.dmg + + Note that this package is in an old format and you will probably + get a warning "Package is damaged". This can be resolved by: + + ``` + $ sudo installer -pkg /Volume/.../wxPython2.8-osx-unicode-universal-py2.7.pkg/ -target / + ``` + + * **Ubuntu/Debian Linux** + + http://wiki.wxpython.org/InstallingOnUbuntuOrDebian + + +Running Scyther +--------------- + +Extract the Scyther archive and navigate to the extracted directory. + +Start Scyther by executing the file + + scyther-gui.py + +in the main directory of the extracted archive. + + * **Mac OS X** + + Right-click the file 'scyther-gui.py' and select "Open with" and + then "Python Launcher". + + diff --git a/Vagrant Files/files/scyther/INSTALL.txt b/Vagrant Files/files/scyther/INSTALL.txt new file mode 100644 index 0000000..3662306 --- /dev/null +++ b/Vagrant Files/files/scyther/INSTALL.txt @@ -0,0 +1,85 @@ +Installation and usage of the Scyther tool +========================================== + +Requirements +------------ + +To be able to use Scyther, you need the following three things: + + +1. The GraphViz library. + + This library is used by the Scyther tool to draw graphs. It can be + freely downloaded from: + + http://www.graphviz.org/ + + Download the latest stable release and install it. + + + +The graphical user interface of Scyther is written in the Python +language. Therefore, the GUI requires the following two items: + + +2. Python + + Stable releases of the Python interpreter are available from: + + <a href="http://www.python.org/download/"> + + Scyther does not support Python 3. You are therefore recommended to + choose the latest production release of Python 2, e.g., Python 2.7. + + Mac OS X: + If the package yields an error when you try to install it, + please use the following, in the directory where you downloaded + it: + + $ sudo installer -pkg graphviz-2.34.0.pkg -target / + + +3. wxPython libraries. + + The GUI user interface uses the wxPython libraries. + + <a href="http://www.wxpython.org/download.php"> + + There are many different wxPython packages. You should choose a 32-bit + package that matches your Python version (e.g., 2.7). It is + recommended to select the unicode version from the stable releases. + + As of writing (May 2013) the following links lead to the appropriate + wxPython packages for Python 2.7: + + Windows: + <a href="http://downloads.sourceforge.net/wxpython/wxPython2.8-win32-unicode-2.8.12.1-py27.exe"> + + Mac OS X: + <a href="http://downloads.sourceforge.net/wxpython/wxPython2.8-osx-unicode-2.8.12.1-universal-py2.7.dmg"> + + Note that this package is in an old format and you will probably + get a warning "Package is damaged". This can be resolved by: + + $ sudo installer -pkg /Volume/.../wxPython2.8-osx-unicode-universal-py2.7.pkg/ -target / + + Ubuntu/Debian Linux: + <a href="http://wiki.wxpython.org/InstallingOnUbuntuOrDebian"> + + +Running Scyther +--------------- + + +Start Scyther by executing the file + + scyther-gui.py + +in the directory where you found this file. + + Mac OS X: + + Right-click the file 'scyther-gui.py' and select "Open with" and + then "Python Launcher". + + diff --git a/Vagrant Files/files/scyther/Images/scyther-gui-16.ico b/Vagrant Files/files/scyther/Images/scyther-gui-16.ico new file mode 100644 index 0000000000000000000000000000000000000000..a92d8228d89417af4cfb8dfc4081c8df0e3a8e73 GIT binary patch literal 1150 zcmZQzU}Ruq5D);-3Je)63=Con3=A3!3=9Gc3=9ek5OD_F;2#46!+#j&kl^{xqb~Yi z$W->fguU{ADKGW^vcWq46=MwltEQO!S4~4;S${2%zJEeOLjNr-E&rREn*KMoF#WG% zY4BgjQ0l*gtLlIG5WWA(@y7qvvn>B>mfHW<sdR#4#aLso{;;sH|LEZB*RTJN9zFU$ zF(>)ItdHh@#VCXS%E_kx)iW&rt7k&6Y@iNUe|UH}x^_7K@87@wr_Y)Wc8hF))_?gh zz5nvz24F1VtV&Qn$e@4!{{7F$&-yQFqxfIKNf~Sw$ZtZ%vP9_znX!BK?*BZhLjU<S zMgQ~bNPsbqq7c#gj~_q&pNF5}Kfe$H^YDP<?H@k>gX{+33BBF_4W$_VTgWo}w^3yH zZ>Pxc-#~(}evsc+uUzrpPM+hxk1E6e5KV^vF**$Y6ZIJWdnrToM@B}1tiZspUcLHX zUYPgaNuJ?<usXy4I30%nS%wV%OU)Sm*H|+AkJrJjA7tmLQ>Xr$X{r9VlVbSquL@C{ zXUOos+JfPKryaxpDb5W4i;YqBfBW|Be_>(ae@#tIP`LhA<Y)MA4bra+(VuV3@W0NI z;eWS1!~Yqs4F4<4Q1yd60J3}6u3i5@X<CSb;lGv;!+#qohW~Ez4FCO&)&HmJG5jwy zWcXiY!SFvBhx<Y1T)%$(e?>*be<vI3|M^)N|BoCw3{KA=a{^Tv{zqyu{P$9X*ze@z w1kyqj2Kh-xh~dAXD8qkEA&7nk1_n?bCK_`vF#H2ykiG^61_pBR|NjgO0F|{~0RR91 literal 0 HcmV?d00001 diff --git a/Vagrant Files/files/scyther/Images/scyther-gui-32.ico b/Vagrant Files/files/scyther/Images/scyther-gui-32.ico new file mode 100644 index 0000000000000000000000000000000000000000..b87d7f95499453981808d80573fadbe935c143f7 GIT binary patch literal 4286 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 literal 0 HcmV?d00001 diff --git a/Vagrant Files/files/scyther/Images/scyther-gui-64.ico b/Vagrant Files/files/scyther/Images/scyther-gui-64.ico new file mode 100644 index 0000000000000000000000000000000000000000..2fb682f62d1421d03c3963a78039c7c9519fb730 GIT binary patch literal 16958 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%0A?LP@>52AA~{e1gJYH@;@jY zT)A@Pe|&uWe*pmj3_nBdfQy65KTv-bmIef%<)Anl!+%gdz!nCeIuMi>O!*o9BbNoB zx*t^kf&Ahl%J3hQrh~;9{=?D(C{KXO!W5*kFh`EzKL~@$P^jA|_CF{LK={j-FaJT~ z6@r3-aQ{N>fb*Fc82*FWxv(_A$HMR*ln+GMAZ=ez7=X$`SY4pb&F~*o9>B^&SXuzJ z|6pYzJRCsjL6qUYzZk=RP`L;y8zLkb{)6j7XxRv=7eE-4m!NK=n*Tvz0Kz9uocOP$ zr3Lph)E+P&mIq*IfQOmkKd3GQ<pWSz0BZk(!T^*GK;;3rJpio}L2V*XSpjM*f!OBI zdJ!HDpnQSUE`Ya*plJeBKZ3#ngh6=;>MpAL9~1_levO%#8Q9NId*EzP9)P6*P#X}` z7Qz+=puRt-O$18|pmYH<3lxr^dJ<GV!rBL*G7{AP1C<Y;dJ>d3JVY4&gUU)+Sb)+6 zsH_0#gPKJX|AWHd_3PLFt*x!${)XE3ACw0`<sdi>K+8hpFaYNTXuA*;*B}haCm=s7 zC@B12ym;|{Ha52ZpfUqgHh|iQu<`*pO@Qi5P<sg!7OqI?0u&ygwiVPpH1j_w3_xW< zN=gd2e+#t_-1dj10Z@AYR2G8j1C%geW%v&Y2T=Y1wVOcx1+^jHzkd%h_P>RN#eYsF zNIwBoK7i^=ke|SPL_UW9pt2Gc7NB$isy9G+9+oyhdZ6y1ssF)_{r~^}_U+sMgVsJn z?SzK`C=GzhLRc7p{0qtxpmqW%zFAmUz<tGQ*RH{g0@H16ZD2D%`2*Bn0+o}XG6Cc- zP*{M|1+?!3Dl<{SLxABwNDtI4bn!pP(V%_+XdW9>R|*LU!Se;kpD+w{6L>7BxVZTL z&6_ttS~2j&ix<IZ3e<N7g#oCH0JR@M{RcHJhX0`O(1g|<u<!t<4``nPRJKCxqMQGb zJpt+)Y}~l<e?>*b|LExG|KZ``|Fg2P{!f}T>HnECXa0l23Ryim8`PgvQBnC1N;{zX z0#rtT>I_gB2@enGSOPdqK;x#MaWrU{NV8Mc{zrGuK=4830Vv&wK>N|4@=yX=Zi2%E z)URe|_zw#g1rCP);B>+X>30ug{8J;mK;!cuKY+?kP&*RTjsmqKKzRZbCLj!IQ-J!| z$YBF&Lx9wS^x~WU2K8HedV2oDFlY|CzrX)KHaua%g#VK#PsWL-O`G-~8wRcGnK^Uj ze{6WxtXco(&Yg=D&zm>zKS(dA?*XbyL16$YJ3$y!kAN_!&IGk9Kp5m-5C(-22!qrU z@;_7_UQP{GJ}3{cF*5uI)uqT7R5rjcsICNKW`_Tu`UO<)K>dTW{DaC58vld*i4TL? xRit33|AvhJq3)%2e2jGe|6yQY_&ZWD=zIXs(Ey_~C=?*)C4gANJv?CT4*(jc@O=OP literal 0 HcmV?d00001 diff --git a/Vagrant Files/files/scyther/Images/scyther-icon.svg b/Vagrant Files/files/scyther/Images/scyther-icon.svg new file mode 100644 index 0000000..7586c82 --- /dev/null +++ b/Vagrant Files/files/scyther/Images/scyther-icon.svg @@ -0,0 +1,222 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="841.88977pt" + height="595.27557pt" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.43" + version="1.0" + sodipodi:docbase="/home/cas/bzr/scyther-gui/images" + sodipodi:docname="scyther-icon.svg" + inkscape:export-filename="/home/cas/svn/scyther/Design download page Scyther/scyther-icon16.png" + inkscape:export-xdpi="1.6494846" + inkscape:export-ydpi="1.6494846"> + <defs + id="defs4"> + <linearGradient + id="linearGradient11078"> + <stop + id="stop11080" + offset="0" + style="stop-color:#000000;stop-opacity:0.57731956;" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="0.209216" + id="stop11084" /> + <stop + id="stop11086" + offset="0.65205503" + style="stop-color:#000000;stop-opacity:0.2371134;" /> + <stop + id="stop11082" + offset="1" + style="stop-color:#000000;stop-opacity:0.67010307;" /> + </linearGradient> + <linearGradient + id="linearGradient11052"> + <stop + id="stop11054" + offset="0" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + style="stop-color:#276816;stop-opacity:1;" + offset="0.25145975" + id="stop11060" /> + <stop + id="stop11066" + offset="0.57149941" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + id="stop11062" + offset="0.57149941" + style="stop-color:#010400;stop-opacity:1;" /> + <stop + style="stop-color:#002583;stop-opacity:1;" + offset="0.8028897" + id="stop11064" /> + <stop + id="stop11056" + offset="1" + style="stop-color:#000000;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient11044"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop11046" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop11048" /> + </linearGradient> + <linearGradient + id="linearGradient7532"> + <stop + id="stop7534" + offset="0" + style="stop-color:#9e9e9e;stop-opacity:1;" /> + <stop + id="stop7536" + offset="1" + style="stop-color:#9e9e9e;stop-opacity:0;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient11052" + id="linearGradient5737" + x1="521.7384" + y1="589.8822" + x2="521.7384" + y2="174.88217" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient11044" + id="linearGradient8364" + gradientUnits="userSpaceOnUse" + x1="323.7384" + y1="278.88214" + x2="477.7384" + y2="322.88214" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1" + inkscape:cx="526.18109" + inkscape:cy="372.04724" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1280" + inkscape:window-height="953" + inkscape:window-x="0" + inkscape:window-y="0"> + <sodipodi:guide + orientation="horizontal" + position="296.88141" + id="guide1366" /> + <sodipodi:guide + orientation="horizontal" + position="571.88122" + id="guide8421" /> + <sodipodi:guide + orientation="vertical" + position="206.87725" + id="guide8423" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Black base" + inkscape:groupmode="layer" + id="layer1" + style="display:inline" + sodipodi:insensitive="true"> + <rect + style="opacity:1;fill:url(#linearGradient5737);fill-opacity:1;stroke:#000000;stroke-width:6.73799992;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect7546" + width="323.44028" + height="320.51846" + x="194.92915" + y="162.62292" /> + </g> + <g + inkscape:groupmode="layer" + id="layer9" + inkscape:label="inner fade" + sodipodi:insensitive="true" + style="display:inline"> + <rect + style="opacity:1;fill:url(#linearGradient8364);fill-opacity:1;stroke:#000000;stroke-width:6.73799992;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" + id="rect7489" + width="323.44028" + height="320.51846" + x="194.92915" + y="162.62292" /> + </g> + <g + inkscape:groupmode="layer" + id="layer7" + inkscape:label="blacker fades" + style="display:inline" + sodipodi:insensitive="true" /> + <g + inkscape:groupmode="layer" + id="layer4" + inkscape:label="white inner" + style="display:inline"> + <path + style="font-size:48px;font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:15.39999962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:8.60000038;stroke-dasharray:none;stroke-opacity:1;display:inline;font-family:Luxi Serif" + d="M 439.625,186.5625 L 228.875,186.96875 L 229,447.625 L 298.46875,447.0625 C 330.87282,446.92031 358.52897,437.28122 380.09375,420.40625 C 401.65809,403.53126 412.43728,382.80494 412.4375,358.21875 C 412.43728,345.47874 408.75517,334.539 401.375,325.375 C 394.57101,316.65817 381.16868,305.92772 361.21875,293.1875 L 346,283.46875 C 335.8349,277.00229 328.44922,270.61422 323.78125,264.34375 C 307.04223,258.53812 294.42062,259.0563 268.875,259.90625 C 278.05518,239.8488 296.11407,242.38722 300.21875,237.3125 C 304.95019,231.46292 305.43096,234.13065 309.84375,229.25 C 321.81701,216.0073 334.34348,209.33336 346.96875,206.0625 C 353.47544,203.07236 360.58299,201.56871 368.3125,201.65625 C 397.62337,201.98826 427.75001,225.34375 427.75,225.34375 L 439.625,186.5625 z " + id="path7544" + sodipodi:nodetypes="ccccsscccccsscscc" /> + </g> + <g + inkscape:groupmode="layer" + id="layer8" + inkscape:label="upper white" + style="display:inline"> + <path + style="font-size:48px;font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:8.89999962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:8.60000038;stroke-dasharray:none;stroke-opacity:1;display:inline;font-family:Luxi Serif" + d="M 439.625,186.5625 L 228.875,186.96875 L 229,447.625 L 298.46875,447.0625 C 330.87282,446.92031 358.52897,437.28122 380.09375,420.40625 C 401.65809,403.53126 412.43728,382.80494 412.4375,358.21875 C 412.43728,345.47874 408.75517,334.539 401.375,325.375 C 394.57101,316.65817 381.16868,305.92772 361.21875,293.1875 L 346,283.46875 C 335.8349,277.00229 328.44922,270.61422 323.78125,264.34375 C 307.04223,258.53812 294.42062,259.0563 268.875,259.90625 C 278.05518,239.8488 296.11407,242.38722 300.21875,237.3125 C 304.95019,231.46292 305.43096,234.13065 309.84375,229.25 C 321.81701,216.0073 334.34348,209.33336 346.96875,206.0625 C 353.47544,203.07236 360.58299,201.56871 368.3125,201.65625 C 397.62337,201.98826 427.75001,225.34375 427.75,225.34375 L 439.625,186.5625 z " + id="path6613" + sodipodi:nodetypes="ccccsscccccsscscc" /> + </g> + <g + inkscape:groupmode="layer" + id="layer5" + inkscape:label="beak" + style="display:inline" + sodipodi:insensitive="true" /> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="cyther" + style="display:inline" + sodipodi:insensitive="true" /> +</svg> diff --git a/Vagrant Files/files/scyther/Images/scyther-splash.png b/Vagrant Files/files/scyther/Images/scyther-splash.png new file mode 100644 index 0000000000000000000000000000000000000000..818997cab57b178f6dd05bd9cf694486ab5f7ada GIT binary patch literal 119951 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV07SMV_;y=IeQi)!BXtx8N$KA!BNAJ(!s#M zAX(xXQ4*Y=R#Ki=l*&+EUaps!mtCBkSdglhUz9%kosAR&g93x6i(^Q|oHu(bXUK-m z{r}(UdC1kh+rRtmntX2G1eQ&kgjo(PYGHJ7ae1QNu|Q*S&+Co_`wL~}7s^eStk-L{ zd;H)>YP!V3?gyV3n6)18bbBZW9GWy?g6+!^^}TnOt~zJA-`=m(dB@zPo7?TyKlfbV ze|4?Z_T87izB~WvAIE`5A1iF+`j0=BG&{k(m$Co&V-WxRzoXm^5ca&pHt`0Kf{zt8 zhk5iFY$5D6$vB28u*Q!(#(NmPKn+Q&V0-~Gp#Qk>nGZ}Cz=rjw&v?kX0BW$o;ZcL> z85C{>3(Ox_eu><Wz?eS2)~vU;cgpEhG5xqRYq#I)+WO5Q|Lo(BJdBDgYuEOAND62O z1T9>mH2-v<hRBMw`3h%5U%b`~eDiwozKwmeoMhMU`Nb9+ZEd)$#YKtPQ9{c>X{iDS z^CAQHIa!MomI$e5EIud^w07gQ1zX)1j!7&LXxS-a`qL&+&wW<Jr7cbZURl|%4BU(t z<??8)S~x+t!HuKSu+70WV>M&9nV71IlhztvM~@BD9JGX12Xbs-RlW1uyg@)gM`GsU z(kmQM+^pNC@J4UnX1sJQuVT%el=zJ$FE6RfRXk`^zqhOGpZ~Kt*KC%SeVG?i?(+D= zp%;R=rPbSZm&?U5RDGK<|L>dhGjlA9XKy_&Uq44wJ4|MQY^BY-y9-w??9(`-C>WuW zxyUoeX_m^7!kI-&ou-_heEO-ReWJ}=+2|K9ZXa3Vse8loapl*mqEo!14a}CtTx&_> zYcTOOycH0A-(%zYehr=tE>pBsnKV5wv!v=Ci#VjA#O2%~qM+hAYts3rcmAF>^a|r} zcHOyscA@Yr4_*mIE>5QfQ;tLh2(@hUSQy~6fN_GvT!p1hQWJs_cr{cvG;9%D?&QeE z*f@#B(PM#0qKHrnBU7iqqXV@Q?;T`uOla8h|M6lwtGZW-?=x-7&aaP2QvO%@rHrqV zamMMV8JU?2H*TDG?wsGP+qW-9$-l_u)oxnw>vqNl)BfYdAA(MZugK0|Qk<xvV^!^- zvOwjQ#HpoRQ@vV?)`_o8&dQ#}Ic3rE)#9RG3eN<#Z_c@yb<6tp#%(UMj!CTUNNLzM zYu`M*CJlF)<t~<vit!5~-Y9c8Z7F56QkkNay2#*&Qiqf4#yiduT3Q>OUUNlxA2N8* z`&8e!?v%)Pr9?p|1(t-^FZ>6hnjLpFslR4fD4=(Voh_U78dF#U!|H<z0^KghtERRd zRWgXUQuqH9kN+p%#2@SS&#bxDc<;FNOy_r+bI(8D`QZ?^<?lC}Eq^|lJkzT5mD%xL zL!IbtJ?`?gQ{3e$TYkUaKR;+?NkiG|j}<oT_Fk+qm4`U5h-3vAsd%b9-QgmYUA23c zhFEnYmsqc<=F}jksGD9JBNnN}AHGqT`{mn|%>4TYUIdn!m|xwT^)<?Csa{Ez#_Jgx zT!M!#-M;M|n=6;Cqc!Epr%J7<MvelLUWlwVWpbReL_l4HSC31aldDx`>Lj;QGv3Wp z;{9s6XXB$%HCZ#sHHWwu#Z;J<9FS-(+QpYU=f&m+r-E7D)o40+sWTXII6Uz4S$puq zwCfRfj@ta5v;WsOLGDkziH9M+c4Kf0JaT>CH&eUsJI`Odb7#-p&r7D9nPJ#0X`J@q zq<`I{wb9#)KA$!J-2eYae@RKno8z+8Hge||9=wzM%xKY8!PUG$9wB;4Mv4*M#jiPv z0$m(tF7+0>d_CInluc7dkfxgNE{{uGtxmS3rC+~%`O;)?W{zd+)cl+T@8@Z2)&_J2 zD{%*LXg!@VORCjSGb;PjPbSZ$O(8<bykZ9;mV~qfHgGvJEuG*{Tg$t&%R$T0KVH7n zbnBYfoqZc8A5+Y2IJzTX(S?Qsw{%jq6($$0>+{cUDLI*!oHOmqHIF5$)sJwVV03&D zXZhj(yxQYiT6J@S{iJt_2koCHTj&w8*>A4Z)ct>+>eoD$zJFuk59yv|%hc@t|2)6B z<YiFW*;!lr%RtplyV~Mgw<N4HZ5YCK*&o}rWBLSzDXz06ba|id@R^m>H?v-*{ro)F z%N=Gtof_i7Rlj$wII?%kmL3<OO{K5Jmib5?UUITsF@-Oir*P7O;P6GkI@2~<sd9)k zPGNCu5NcB3n7}b5DAIPmqNmmpE63MURCE_ES+adK`{H1)r%Hu8ozj21IjuC>`25m- zzt5827rf5DCvc7R(-Nj^!D~tkGpGJnWKGz3EMV1<DVL^%NcWgUWEZag_C`BI<;lzc z@4swr{n9$^_pD|+CX2*FEOM1k1l9cK?Qy@JnVb9cl=k{3x3bsYwU)MSnQ2pL6dqq| z`uJF{w8zZ<FWl`HEnof|Tz<cCUlJly`X_LQ$4u9VMuAI9eb%}u33yBq(O{YC<rV8J z+}YX5HOVvhc+wdOv;239iZ82eEBiL_*sQj;v`Z%b$CsToF}rH~_`^({_<cPpdPzNJ zvly7Qo^I;?rz*9SDJWM!VoFd(vca*0EpA?(Njhc*8Iu!wR8CzF&^yi{BII1|E+4pK z;<IUiJ7&y1s<e@*M_cgBz3HxB!@qEL9#Ghzu`=e%1y;^j^&$zykOooB!c}`WAFO+D zx8DBoj$hmUtYF^T|L}mLE<>xpox0y|o4f3@b-&-M)<19anP>f;Ph79BuTOt;q|;}% zS#RX#w2%M3@1K9`)~(z)<D?@Uf46*Yo~>W|(!1u{=J|KiavvY-y;JeHmp#K>uK&4% zLGG=RCIgn&b@!qkE=t^He>RiV?U7E%8rS89Tem7RHXAZE9^*LOG0ke0o5_XCH@$zi z^-l46osp5VAoq=h)h%;jmnO^Nv`r}|Pam0TcVU{Bsv4K`si~V@i*1{BYnD{kQl(3t z8*}2Pg-GX25>lU~!E>@z&~XJvNMliq8%HOXvswNt7uK#{&(gL`<<Q)4ZO3=zO-c@r z??u-yxv<3Vqon3b{&$>-hG7$=dN<Cx60wBqgKNX@X$4bG`q$Rq=47vuKit|J#ZdQU zv3%;mCf3l`=k0#$)c?I+e|G-=KhJZo&98Xm`+LE!UsZZLp9rnn`z>mj|9n1&`1t$# z?tV~g3c6aGlPDqAFt@^H9<%GZ3C}xjZuVGOcG2MVtQRe3tde_=axuFlPF=MAM)$>r z2@>3m6C#aUOJ%n@UA`0LpImIK9alZK@2u>TVnN-t$~X7yWY*k0!}v2tTvaLS(S3YV z+Gb3d6Ex*i?UrqQi$c~+IDb9h&1+}P#%t^5`Fjc^HcYwnH*nqVa5hFSc8S%RQ+0fK zzpjbiI?*$*Z^bsb*{<Ijbatr+1SzmamRv|O3QYec?W~i~yZNB!+zX+NMKd4%`>;T~ z@psEb@o>K2g<tp=|2^Uu%lu=df9<NQ+|SR>&Z&O4GxX8>w_m<|DR|s#ZdCm(2UH?_ zKBc|>!;i=P?^my_vXMKl*vutj%x8b+>MzOg+i5*#kMKu4W?8s(!CFUYXWv|2M-hX% zM=k<fijG>16ZAT@S{)u`v8l@!O7tqbZ_GRU`bZ(a?poze?MeIQ`Ss1P>vUQu*lnEG zr!Bf<%9k%C%1c;Z*ZkL+88La?PJR|EU&AP2bwjt^eNSTamc*<}xKL7Bt~fR2b6Z(S z5X<6?k<IKD@5L4GCZCT`|2Jilhw9ybtw*QM+nL6{RAga@#=}L6>=^gFHwd=Y@G<iR zMSN#-7(<_&?X2>>uVX`BUyrZ1l{U}2^Ypcf=b`@kKgoR-k2vano{oQaRu}A3&(|-+ z-1>75bFm$fe^B!&XByMCl*|bAnl0B>2($=AOkT9vO>m~~r2r=d7d4itiGPn>&AAt} zq`27p){-6>OQD5aN1nzl^PlfDCHsKXg_VlyR8$I`mIk?bmG^7#Y(6P>YH5~lm!a5V zUMtfnUanQuRW~-JY6odPD(c$W<TWWsb7@KLt)30nI``Gt+t1k{dZV#ZJ}jknuTeH% z;ErAPovW2Zq^5>CGyP?2nzy&(?9vxMSMz-_Ym;SP%P_~XIPF{X{cSd%PAIb{n9KDa z|9mdt%Z!UEPQtDWxw{m9_rBY7WreV-rXNF^Xvvh*qFLFm3ltCiTNgRel}p#^szfr| zu9WV*s-J#FrJb48%=7t$#lqYY?luA0?}o+KOg{arI*}7`DI}Tq%a<=oEvobTIhq)5 z=ilpb;z~a|>4<0A-9;Ktik>X$FzD%c%vGrB#_{5n&c%I&wl}WqwBEn;^mPuy2aGrF z-%u2|+0tKUsKcgK=b;#rypf;ro$wdV)e9!P`{Qyx?&$*2hTPoT(CpgU+BGpdi~i>y zd;GED9%D=5i7%GzmqTv*EV`=`*XWoMY;xkrore5*Ti+$KOf8zIacW_2q4;L8%k_62 zxozK>YPKf2T_xevm%|;oJ`2}5B&INXMlIa9P;N5Ur6TdkYW{AnUn5?#B*=tM2oelG zwZv-Kx^2gn&Nkkt){^~(<1mBhlL?J7H=HHd^or6=YHRmKa7LSzU*4PQtyW^ZF>BL` z<=dF=?mMR#)i8DDvCSSc&$78GwidRZ{Pbwv-Zsh0y>s8$R`Ij2=L&o1O<x_gdgV&R z`R9Z6rt=@@o1<a-dd=n;*5!JO-Fg@8+&QzakMG+0`19TR`%WC@w?DJYcXnAtZ{_D_ zhGlOemP{!rE8CQDQAum+DY>`V*VaV#$lJ?ls=mIqHu>YDqqk+`t;=+HdGn=K@jqK? zQS~LG&*D*s<NEuzZ=arJn*A-KpP{t0G^XUDt4!^ei_CNHg7p3T^z=^o{n|a>Ze>^3 z^lw*Qn)2_@&pCz1BzxrT=NTp+3(yeB$j?u|yv$c8a#PFwKhMmq|L%I*QTX_nVfDA1 zCWVBnt3vnuc+?>&Did$C#p%sy?&Lcr{hE!`D68cwFxBzTfYZ`ySg?cFUdDGcLZD z(^Xr$W!tv2w3AHf-yXTlJ*joK=jOGy=OVo0H@ZwY&AY`>VUwF64^yilo8%6W*SD^| z-XJzB$}Nc{V)4dP0#~j%Sf-_9Yp=e(X5mUt!^%r8VSD!RtWD0znyBUK;kq=&(PhHv z>p^<o1=tilWzrYl(J7P?W_3)H%bl1}w6o*gJGmtjrkrx+`f255>pE*za0}O6Yf--o zY^O@uq93{_-mDg4V45zroo%`8Z`Y*%o%;k+@)M>y&foLNAwT)Xr)d@64<6n5eBSB& z`ro%#eQo6y|McN7|NHBE=M<l_toi#o{`nDM|2q!_3bJ+k?f+T)|G@wMfc(D??W-Qo z|9K|;$4URXO=oX`BK1%!cX@UG^|)%?`@ipf-xm4%)AapkzVH8E%g|@{D`Q^evzd;U zU+(VOI_>A@=lR<|KD!zoFZ*K4yYyo{lFUu(R<7*KuYDa|^Cnq-@w#<+yT4byTDknk zm*w_n7rAzqRj>bRVs8F<>-yT>)B5}81THSi(M;`mc+p+{>FW5uTK=|QuS|G%`O>9B zyGmbgd%0-ei$&c#p3kdhkgzOL*?zZ7I(>faw*~9}UtM2!l-=$_qvGAmk8jG}I=00y z|DT~w<-f|b^EN_Gjw;SUm)0B(P1vFqASfy<xLj(csn?UKDSu}@eezjQ*}eZzgtLP3 z5{Bf`dbXJknkB0$zn!m7`_*%JW%e3(&DM?UxWgk3MC3f;;t5|Db@0SQ-<)?nk(;w5 zZ-^+~J+a-PwI$F);+e+Oq(>IVZivk0G|pvAoXaugrVM{>fRRH=+a=yo-i*l?%*t4L z7vD0_xUg>B1<uIXJ6U%f<4+f7j_{r2k)r7Coh*Axt7_M-85XN%I)!u#v^85amYrD8 zAKPqM^tbWeu?<fb{N;<=m~?c(>-hh_u797Mdh*4^#Xld*|3C4*?z{E9uj|U+2K;IK zJk{#!mEfO$-`AgyEx+rUoc!4Ac=*~?dPTOM&lrEta5|Z8_j%^3t>3<VYy5Bj@5kfs z9)B9E<B!YN|H<3?t%+MN;pL^JF~w(1twrh?K0iPI{N?iba$jtDTUW2!)s=dB+Q+B* z^_9yX@yAU0&|`e=L8tn>2gjuIRk{|%?hDV&&As|PIXhdM;qo%y$DQi)Zmj#k9RB*% z$2Zwc1}XOp-FHjvy0WN<OEX05rO^_%^!i_Cr^m7;)U&UfBD6M`%e3-3cXsUCIkG1@ zqMmP0*LnMPc7WH#3s)GJmWWE^3S3KCb1<QkOYm5h+xDKc;%e)~(XTV5ZgTCIwSUK? zq@IOAD<>RDeU+6RsO7{t)il{cTfAp!j9##&`jSppFLjC1XW2JyU+<m5m>r(G;L>*1 znZAsLX8PyEFGMw(-JBC&a_w<qVB?|~pNOq_#?oeG6OM4+nzcs!$Aa1tIinlTl+xa{ zG4Jh7JnQ&7c2CL6pt$<KUsrt%_P3pSJ8ySxfd1~iC(q0@uKaXT-SX|0%Vn>>ipSR& z^4tA*V7BPv!ge{S61k5{r^oGz{yxLLzHX{#+0vkg`+mQZ{!x*C*8bg_H!`2H*X@31 z^=|L?dycOyx4R3l+$lKB8&mmos`Ebi1Kaoi&CT2M@z`CXzhX`WS3|=;zK;JtYu2n; zcX!p>E4%ePSlBMNs;g(;+=U&!{psa1P4oF$of=jAGBPrna^9`Y{xgADI4?A9d(v73 zKi;LA${ycdvoJzyvi_BZf=Aw|xm%pL1d0~$ZCJj1I;XJut{bzq&WtJgTK;$LmSYke zs!pD-vfVG-+}HT=aa89g-iYLjQInTRH7a<Tcm^$7Cb0A7UN2rBZAXqK1s7MwM2Sh< z&Wi$qCa+iZ6KV;Wa!OS|adp@lWleG8g|Cj?y}4$xq{N2yjci*A|N9E{UKCpEc;dkW z-<h&W5o^5vdi}p?GeKsHX#<1#{TgFX$-VlT{=OecmrR~sp8wC}?%li9fA{(N`r3Rr z!0a=}qVU4w`k$xcE8gvV{^G@p2OAFaCBM6~Q>N@jV(6lhe}8_;R6dz#^ZiaS!;!)> zbIb3Yy#MFy{hZ=^?slI9|Gj(vFYiQho8HbRlU8j7<))I-Qr?<BM}+-1RDI1-^O<3= zBzynVt=ZQ<+5i7+?_6~jM1B7EeSiII(`?=K`+jM4i|a32xv~>f;04dV(J#;>|M!La zpLgZ^r6)Z-U%vl$?7mM^*N3bvFD?Bz|NqbVHeW6{=iGQu_gKa>OC)_xA=~trBG1q% zAJ%L>_vrth`Tq~M+y8kOyYGAS#Gs<%vgHP;r>4xE7p)^!{#s7%{5qp7AL-;{{YNF7 z-QC%9laKBAWdD|>Uw~P!lKGJvhvNdK77>nxf=)?2(kGYo9?TLjb7XsU)>As-)KaCR z`{MkpADd*&e&zY7C1#5Ia;aY7*(?1{td<cq*|pte>FP7j`uwJ7UAkp7ZTY;)zAbke zr%d|QCN-r;;L@clH+<a74_<A^ZuZpni_vlwVAIg#oT@ba^uj|O_wGgYtQ7EY_0HxF z<CrBaEoq-Cb%{;oh{n<lVF^91Ck?9CD|$*bpWD21g`m^LJ9ivB4o$p#D`Q>mtxU5M zo0G##ZBA?J{?0czyds0C_?6$i{O{Hw7Axu(u3WwP@z(2cxARys54Z8g)c^f@r|7h9 zb*bB9{raEYdb?gMTJ`m~Ty>9s{jbY=zFhJSJw9vp?4Ng@+Z`9*_knfRtb1QJ*}Pmb zdE3l@qC17hd853`PiZda@l4@VjM!TR>Mh?+``g5=cSDWILc;#%N&i)s)?AM%=C%L( z(!c!Yzx>n<QU|tw{&1MT`0v;2pQrEtlbYb`b#i9<ypyu!cMhJIsJuGv^I`da6ZGpo zcJJQOUcUeLU7J524u{&$m|yu!((cDWe!f|C?B<5gK#{)l*Q?d5`)Xe}%RhRz`~AI# zwd%gJLaxr-SM#%o&-%@V+-vW4K9~FVH2z=f(Qfg}ckY~NV&%4Yzvpws!&dPh@5=Y@ z=6-+Sv7}X^MA4~3mpd29Bno`Ev$@;i)rrLy4kehh1TD<%I>_U5kR!##GEhb8z%I)J zYN<y*sh*i-ES#%zOu|WYk+0PQ)r{W6$Gdp1T)q0a^L(9<lj|gh*cs|(qHB0IWyE<U z+xh2D5^8Pww9L-Re9hxt(bpL{njely@3r~)WHHBG=Y4u9F2&q|5`n?d{U@$oxOdNU z<&}1iq#i#*CLh<yt2<Y$))sJOE&9oznjNt_QM8wrmqlyIwsrHCJ&W?Qdo1F%tyfvp z>bDN3!=jKDLqn&Qb<#JlY+mReaQn`o7lF#2yKhAr<n!eEF5b&<hk2XY+nVyDq9Hk% z`|tQG{P=TZzQIO=iph@)o-OcYY<_LG_sJx0k4Y&P9_Qxf-YL24YxDI=@SOU8KdYb0 zKdrv^d7k6Z`=ER-nLfvG#Si8in^L(!WynmURIcy$s^1^@C7r)#<Jn5kK!W!)ot0I8 z11=v}KBvfQ>W|lN-aG-t<b-vb*KfR5bhq^S#)5~3a*xRGFuCB&Z+oOueO|=ZN~Rwl z+U@svf9>8G(>FVB*UDF~>u=|7FFd8WJSY55<7|n~*X#dY2e~Ws_`jF)|79-!F4wcY z%RXB-Jf@IUJhnv8-|nZ%(WHr>QU#PcV#;o&#{H@Mrn$L)p8LW8hbHOeX~v6_S)9J` z?<>8g#k`O~doH^ilcorpV|c!KtCL)#B2R&@__4?(5x<_lI&@7p+VXqt`{FW9D^*k1 zHGYPkT?Q*R&zZ={BH+>5RrJLD+C`fx6?dQcXLp&tl_@;JvFxmcoU_By9F1>NHAGKO z(K0ObH(&eptc#P<(xY7rxr&0EOLsW=mv?^a^9x%ab^g`W)f_IePmAO;*JQ3)pZfS% z+_Zf=IA%`U_-$>n;r&Y=xj|#mEQ^ozJ$W-Z-LU?egp1vW-u=~$)n@-P_IKJh1kbX2 zaP)qe#R^u11B?6ZP8}7G_sP$HUv}Q|-;c*T-|zbkPUSD$?RU9<ZH)hMNPN|`dG-G) z*X?-36~29w@V30Wr&`71PCT6+e~!QYhx4_y(cz`%&YItk*;@ATs5t-1ov9nXypJuv zyES%Wje^JJDc$<}cC7OL`Bo=-TMwwY8TvZ;SkJ>5$$d9p)`H7<k?+60z6NE<@|#J| zSI7U&3biUb)+4z)mig9s@%=xJI_|$GcYfcpjXNi96h3anZ=?D0^~=SnS3F9db?CGd zEWW;Jr9{xGGjA-iUmQqU%a*)yO7bENCBrtA(&R@1=XkA(|0kcGwpOO>$3vevW}-`+ z76)iKu}r$c(c?S!{(_^WpOo&p2xhLx%v_r3qq{jx-v9S6^N1hs7O#-EoM>{f<olON zDx8H&Tg*6vmWsT}a%@v@ROCqQ@Qj(8G$$h@#5p%s*;o11hGlGuy4ly)FJ7pa^j2EB zGV$VM7A~JzNkYB8cTI$|S=pL5aH?&2@>)4+(G;u4eg?nJ&T>3|p>p4I!)agszOUOI zAAI4|&b9Mz<bSumV)24i!D4lfu%AU^cwA*_`}4E&Y-dO3?QC7@J^j<f{+g5%ch?6m z_j|hceQo~LU*Y>cO;xPkdbjHJ+S|VI_sVYPW~|*FDQ#Kwgm1U&{jQ*_3mQ*zx8F5e zV*4(8-L6-w<}M5Pz4Pz4+w8d!mY+^2m;bu8{dx$~pTqWl4o`UX+AQbB0bcVv0bA=n z9u<H8$@Jd2^Y#CVL4#XwzrD7dcUP6i`PQ*s*&jEeoPRGn+aqB(=}h-g(*ll(rC+^R z#5C{EdHecQR?O`-PvP_}Jx8KCE4w*_Zq5(dcw%Py+^0Q@So4-hGi8eeN;CwpI4x*# zTF7v{MRDno6Elu2OLN=WGGj;IIo;D1KbIs22L5f}2r*M#rxL-lutg!<S;5JCDRal7 z2~NJUrmaz*T01mCRva)Ya^ZH;a1l`KT`J_R6Sbx1+t=)iw~|;TxX*0}Xb^jGM5)Jt z`@5w9#}?ks(k_1HcXFzCPyfIB<MH3B^Zb4Pm@Ff2tp9E^#X^NeVaK`$paB2>qyPU3 zA^-gJUteB=Mmcrj_EdNX&e?q4ZnswNj-sbta#b%D-o5qtTg3jlzYDJ4xoYy^<?{J) zS9g5)^?Lp1{r`9WuiJb}64Y*K7x}3*)eF=j3Vppf{rtU$ub27FJym#IcKg{|zrMcy zc~rk{<LU43p7&Y5TM=db@rZDHjch@Df9%@$FBRX++~taSqL#1Qb(X6osH8M^X@JH9 zrHH?Rb}y~6j9&}4pY&N|yf}lq)9=Lf9qcP7=-IwmGSP*@QD%Cklws4!$?Ae0-9nKe z7p2y0;COjtnOoBo4@FKV0i^>{-3F6VPf!1NYtw#%>U)7DTf{S^Lyz|;_Z_??FgIgc z$=64-rre$Lpsh{He0BuKk`RxT23Bf%-zSEhQpxOGGO0mh;t|cG_wvlj%L2nsEDrIw z_1uPi>sg(I9>uGXCBeJ;UIeVliRzfGCNBN>_5ZTT_qW{l=$G3y`^dYZl)ss0)>U7x z+kJoG2}NZF#$CI2?|ijt^$g?ma}5{Y_06!YHtV<f#Bn{g{I1^L#jzU_9IxIwC#6+3 z{os*{KcCO{udV&-7jGT$>w7}?zq_T^W1Z`K>)YQ&-<&!3^hx#b@-o}sZ#FM^dEvPi zUzoN<{=Gep%P+m*NamRyU-y&mw3yAjTG!h*%#Qibm~r-+X@Y6k@|Hl82dCASI4LnU z7o5}gd)o0Yu%PU~^YamoOCuHq1iw~G?eJmw_TNXeDMs<pip70LyaK#Zn*5VG1m>z& z9)_(2kXRFR!l%M3d4pM<v6lu*nC85iUzz_toDg<N>^vFVzijvB_RZ&N#7%n_UsPMV zdUwB9(8AT_+*7?KdPE*_lAAr#K|RxF*0CjO3q#&44br<Dt#k46?cOdH&o!DNSsLHU zgu+eq_3P%Xoqb*S6hq=%#Vv+XO)Vkq3CRXh8#J;{v?|T^tvRr7OS_JCm;NW0>+8SY z{`+auH2$7nZ$ROEN>P>JcjeEg(|5jD)NS$YM)J<*^Qy}tW-p)e$ol?IzWu+ht}lD_ zw(OMV@{qNA_ZBAR7v8V^zOnT6wcKl5t%v-UJGCU9Xcdo(*jl%N^T6Fi1ICEx=-r2} z^QbYzS3GRJyX*fn-RKvuZ(p0Gz|rJrJ*E7}tE;Qqb7nvO_=fk8LCQPB&kk8zJOi|j zaCnD*4|D6waGX8mO4b%L=F+-j64T$ko&Ry#Sq3quNm4QG25k<O*A29DmWj{hSd+i% zc*czCHM8{=@kY$9{L0xV!lbF=q!prO<ZEUxvH0%RB`IfLeVroY{CUYqpP851Je4P% zQoC1uZs&^ye3~rLR=YhP2?gq@Y@Ova!`)+QthGbefyzIUFW$XMeEsZf&b=Fs?!Uzz zg(Ubo#apI5+F_XU&ZFY*(WOg{=J}XikBGQX*d@ePaM82(D2GSuoy>11gMG7v|7Ab^ z{{6M>{p(exyazArO=y>9-^%~sT*bGW>EN*a^WpH$ce`Hi`19%X_S+0a|9(C%e!X^k z(M4Br-YiLB7RJZN``1Us?<#p2ci-G$XUwy8yWg$aB){{^CGVY2r$ul3y{na5Jk0gz zyt-d6YmMB?>y2kTpYI)+JOALa6+Kd>UE1q*ByIn8;rjJ(RV!&}Y4+S_A1nCG(&Q|= z6?zOJ|IXX8U}8y0i9zip!3CFe_|yf$(vxjkgqyD=t#wF>y>c#t=O)Vp0~gMhJ(Jh2 zo@snYp=C+x84a$)KBrt>C+Q_3H)oh}ID0NoX%kqRJcVhYh~ot1t(rlcQ#MY~GJJfz zH~C1%N|l8Ut+OuQ|C}dR@u1Gnrc$oHs)$ee{txb{JA78oP!35=5fSQ=+1hGV^>{6Z zq{VuthqvY)HgM58@$}V6S4E?q8#^}6-By^pCT{nvm^v2ixM*kRV&TdB^Sig@&D+SO zbm_{3WwQh}I4uy6(B7QhKA+h}r0#y9y7c3$>Fu>gryPp$%UQGT>GzOg5AFkXag|R+ z?f!l22e<Y?gJPf|#^!nD4_n2Hu7-veKJGOSldb-JV_O|tx7S<Uyj?GsX)*qo_kB<M zwr$(q-YYjKeiWU*w{-rS{QA$|UPy1ae5Kag+xzOR<M#gwLFT^STKiUq>*Yroo*uc| z$98l+7Wl%w;6&u!2=9%{U8Zz*_&SB{Y;SCIvsB!)j6XRrXcBt}!^({%xo;Jxb9?k2 zOPCm0B9QPcu(;yu)o_b<FBTgf^JU$5En%sHhe1?wE}ynZ*pA49ERj-{!a-i1Sy`_t z9)Atr`QraiC8a4hV&=JgH_U#<xo6)aR=r&xYX1FA*Y5D1{o=Ler1RGUI+T_OJUJw@ z)WBsqCr8YZAO{JSn@fZycm<u%oaEK9p>5r~I5o4LC95+ce?405GuM(`QPgpTqt_Y( zy%`C;-3dw)g7~CtKIF{z{iyYC_vdea%j{hb99{hX+V#wLO6@6J71cU%duD)|+c9M~ zQ*Uo|{`t&&zh#E+^#ozfhT5p(U!P3&|MY70`n=7{rbul$#y{u&T~_g!4QHcfE!!QM z|J^Tf#mk!u7j3<_uz$hvVgrFT#m)Wmnzu4#>x4xw(r}+Ot#dLLFYnizdv2fEqWYO( z%e7s*?6U73c4#=dK;(&&bM85X(#{yW_MlU}-jn@ynVOgyX5ERHR5bJC<>gFb+D7`e zv(HLQxT)*fHK8cs-G*aA3pQLzP|bOH$K~{jv>d$yuUMoTr?y>8j*8s4X70ya&duq% z4kv7^d^Ns(6V!4PaLkRJr!oC>ni#iE6N`DJXLR$%yd^QJ>n5x|xv}uBTa<g>qRq*+ zL99<g4m{f``@%x?s?=nOHNJ++e5ArVCbJ~#G_qyxVYm~zX6v8pZU6amzt1<lIa66b zwIuHYXWYE3dx1<F=HJfWKexZ;iE{I`>>f$uHc+Nso4@|&q8PpRU;pl%dT^HGw(Gn# z=PaLxa9(AXubJ@e+qc?H+npO@GiTitez*UBomuX!E&lHxete^8+&|0JPCoTtomiua zmdlcjsoC!Bo9i8ueV+YJpZi>P=H1f{|JN7tvtDO;B=^X3mOxA3Gf@qJphZk4PcEN- zr0ePFnYP(#qCz}Ui+Md~Eh_CYUANL{HdjWo!a=Q09+rhAm(64DE_`@2U99lS#^VV~ z4@FGi;!yqRbZAedI%saL_*&%V6}b}a8yS}db*@_*-Ko^N#bD9G!Uf8b47na#HuoAH zn{aE2$Q;>Tu8jM4{8s7+I4uf3c<k!>K+Sx$35r2dMP7;=o{t*dMQq*~v24ncDO#d? z_#dqM7;^o6L}1jO`|r%PW*w+@t4rB`_x;=h)=I2466N=6&EtPvn$Gq$vHE@W{nPn% zpJ(S@+ot{{D?9u9N{&5Gr$zrbUjOHKt_^p;^*f8SGcy83Wo2~!{`SlGcSCsBu3f8M zvF!i<_x<PP_J1?`*YC}{YXvG#ZTIyZ->hF4yZ>=axbBWGs~Vhqbv=bHZ`?U~rt#*L zj)zLmd{a-D`|r}1_Wvwm$(y;%UkB~7@;za0`Z(%s%=R}AH}fywxwG$jd}U|1T}k1z zv``kaGwb3V6+D)9>q+GbdQHgcy((%V*g4f@A(Lk1%b(AG%+{}&C=#&H>9~}p$dxA& zcdeSjr;EP0yQ^uke;q%+U4?PxoFL8RIrr`yTyd>%g~P<tqA#?+DHwX_L~%?~Vf9*) z>6OHLS4m<1>C4xzJ3AN8OIpc3``V_evr)%<auzRJC%D>)N6O$tK#;hbf@q>d;?oOv zS=*FtGu8Ls{9^pzY}UzI-P!tbf48$FU2oT{xOb3A;KBX>fA9Z1X1*`*s)=Fgt1GLD zckkZKzSpg`_U{6=qt)G}+1Eb&zW;xo@p+r#*<Zc&_fE;Lc`VH=fBnjp5Bt9F&7WOd zRaNzErtjH>PU-3CSJ%8y^`7=&b^PB~3~x_7zFFUrc;e3D=c#jd=LNM+;A&BwfBN$6 z%e^9uMz2qZ&b)4TO=)Vuzq0(b(@*Vc+**25xbcX}tQxy^p#_2_rsjsfPgL&t^eVeY z#<0sNS=Y+b<I<E6))fXvBpmr1wU|`84CIqM1=viulGl1)4NJNdaryT3=Af>S<r#}N zrhM%@G$Eg7M%@jcxcXYd<@3w5{{P-D{PJat=f;Rd+sypqH+IKFELgU$Z=V-`M)>FD zrW%Q!lSQ&w69ojGafuX}ewkK1F-$mo!P=#5rPA9rJ=r-uGb2~!zJXlgTnWDtCqvJZ zPervj0*k&c_u*Bq+xn61)Uxyg`a&D?TOV}xJ~!N&cF%6dC+peeDO@||7wxoJp?c!Q z#l@?yZBu7Z_no!n`uDG8Y_pwze>3?|`Fw8p)t-X$w%-G^-tM2-#jf1k`FYv0Wy~9d z`_um$KVPx)Nzp}zUDp&Y97`$AW45y1cHz<`x11pLS4In8JQ2UyT=~H8ZPuR_34xvm zuX>7i%0&1ouq>ZbXB23ca`W`*8K&8MPfbc!roL{O>!P%YQ(Eb&gwm9TD^fa|VHz$9 zC)*i~cp|qZiMq?xiiGX>`_iTP;tUftUtTj4AG;i-z$-^4x%wBM@>EYe+@aF>^4-g2 z+qX;SYF)Yhj3b0`iA##wxj>N#+D}$!imcESIU&xpD8|9rSvXd9?vv(@wRi76`OJFD z{OgA&^XEBfb-O0zb_rQ#g}B&F5b)Z=`QTjSt=}r=zyDGEeIjjg+C7_n+ix4c3N?P8 z{r5`TzE>X}$m%jAemHmO;E}kE5i(n@z3x!{_E+F#_4~ck=gpg!dks7mw=Cetm-i3$ z{P}b`G`l(SaD~l#lc?KnhGmB;dZx}~D1Pm=<A|StSJzUbv&yqKt&48l+O+0B^IG0x z77L#(Yuds5_g~$ET@|ebp8}L;7^aJzRgSu`CsR09*4AgP8SmU99+DUIRVS+)^m5GM zk!lvzjA-1zl*^KtB^ahu(j+uVef|&O&Hb~U2c7Vm#LaxYU=fpgNHfFC=1yU?4T;5P z?pP+zu*hU{i~jY?Ysx9km3}MNp1pX>h)KFd?-1v@gRC8sjjm-a**3#OmB}T-!P{4L z<CQC3TA~4F>}m&3ut>Hf2nS_PIJUIq?(&T1#t+-IH)?*Yzy3cV!6w08X|?s+|8ljz zKiWQIUTp8}c=hel)x7%mJ~9>D+w*F}hgqiCY_{KLrq5d$b$i~@GxwH6=zNO*|201J z_20k)zkXGnv;BT2w{LCi?rHXa9`c8-zZtto<5u?dTk~yxKA9Yvtv;vV5aW%`<D36; z9GWoG{hT8A%bioQrtRB$ZE3*TvsOjF>rX|$zO;Jg-EIZp=18k+Q5W2j*DU<+8LKm$ zgSpjg*0E)2&t!^4G^d5G*MI&ax&L@V$Dui&`9t!KNMGBL&E2_yDcNMI#nG%@p;Jp& z^&aKm4BJ?9GrMP|fnB$clnz_+9O;FVgalbuNVz5l+Xm)pzYg1ftf^eKzw4E!knhTf zWxIDz58Bv&>=>KDrO53kbed)^c@eVPo>?=^TYxp^<%<Q&w|guNadKsRI!{R7{<qG~ zIj^To^HK<H*ub<j#wOdrv3ga-hQHz^OJ{Ertjhm1E#tw0<L&3x+!D52_3w-Ao>L#5 z%IY#iM@6-zytA3XVDtaa=k3{oo6RNHNdGu2|Ifft-~(v+QjOjIvm347?MQAH4k$a4 zAZD3AU$<t(hbzJUp=;01Hb3vqX!|}RP0n(*hInf7?HHR>>G#ImwzhYlEYc8eElXf( z|1Hr|DyW-yK<bWZ!RE%bWoPATYh9Z(oEX&SRS6kQP%v4)f72Yz%W91WI;|cqnLR;( z<&~~yYJii{Qm2&}3U}A^s`=?iUt9C|!^_K^!M%olTV|P*{=QtMpt`nI?Rvyv&E<1W z&Dt8f#Y9}f{v(G$m)FiGYx38)avtqCmew-$uX6w9TkejkohwyRf1Ro=`BoCB_kB^Y zuL#$+l5YYU2Y+py9kIQJw{YW+X)9K_c|2#HA;tSm_V0~5xna}ep83!H?oeOpsP=`e zm+hN;`uD|+6Hk0TcrpIQWL^GhzEkg06j`Rnmfc*iwaWRScl@tQ3tpGsul>H@b+aj- z2p8+Rz29yr-rpUdQSfwXxDd<kYw4eVJnsMe>-GBl&DU<-I(4X(`}?mq_YYorl%K!E zA|zr{3a9?wFF{v-m0pi6XDEC8@lCbc*50%?KQ^wLz4-oj{^>Ke7$_{Ux^3<8xaHrP zrDvDbeX*~|-7iy|#htxrN`aW5$*myG=_gqgjh~-MN;&QEXvraO{XIuIj)jFN_HXrk z_F3)1wFR3yl^7aXRas9xoj+G#b5nq3lYt6{PWQi0>3vqeB*b;6Omb<S#HDO<E8~*N zv8?8cnvTxAfdNZ)rpmmXea*1^o=(wDsV&>SeEoXi?$)V6@59_ot}bp85IoV?CZ5bQ zRb}Dw<u2jj{Iz@c9_e&DePZc`RtG_0(OEBEc1QmFRHVe%DZ1mzdgC=^@6XTX*)N+L z{4Vmp{+^j~+pPtw$}VjA5MZ(WtJbW;&c+3W8wvur4g~vIwnpdgojO%J{L|d`HR;=x z3f@=W|Gneiuh*-uiR(sfxy$ijk!v?wFVnxb_y6f0mnlA@cmH>bu-}8D;_**F!=?*1 zXKg>85P0Bx?YrVRrPm^Fui5+I5Vua;p5OnxW}D})i?aTF#+X0y`xnq^wY5>Z|9m=a z`Tx&n{sVb7^J?7%+RoTj>HU2uI<Zq*HAd^kq?-pkJeLM3#s{}wTsiw!Bg5lk2U2Io z_gsy9yngl6$vZL@oSd}rnuJ?VR^qii$`@C<MI7BF`g%s;4;>w;Tu12(*POC8L|GeW zuw<_C6!Ogpo?;@AZE#LkAT`GLM7MWb!ml@n1+^G>f;4+3o|_Tn`J6k0r>Wt_u^Tm~ zu5doSxh0c(vicRnqBkr;xi42A3Ar?-C}x?=^pjVwEHYh^`ADhROOTZ@P;beyWe&cv zx~(;~rma@Hx?Ke>T)gTUq#3+MB=XCV&nhp)lwudH4_PR2{Kl4^Znj-r9_MHOS^0SS z8hw4~jvsqZZoBAk!!c?`Y(Jad3HfuHzT$8GxSZ#+)L?zk!YRyf;`!&8^1G!v@%!e0 zmTmaVHp^YUe(n18&!zAGU@N~@`FufBTKdI3@_!z%hi11rHL}as6f955JJKOo^S=82 zWB>YJmm9902~f)3ey7O$>WYP%&)dy5xO44xhQIrMUbO~wpBVwE#>FcNUa#H0sqXKu zRbS)(eVPthn<4$_tDn_NmAoAf+3Nm%p8vl0ZKX|huky2VN~fOANjUxLZI7wnugHl{ zi*%O;$@lV}6?ye3L`!u^(IWpe|K#k0v+C>}rVDRly1u2+^~>^Ux@YX4x&%yek>0gy z*Ns~@Prmq=n;@Fe>T&nXL-X10EZ25;%$z86(cU^DJ8AJs6}Gj!g*#gUghbmiR^R=T z_}Ye(S#rlO`-gitcqjeRc;x^8v-`0vELX0ZY_9zJTBiO^Cre<*%7|UnzctiEy_VWZ zWn~K(shoH!;MgFb*Q(9rD$*v>G+|ebL$0DzN5d5^uctF^?dtgUP3~Cl>~qrE@vc*M zM{IhdI<Mv_tJdAw8q>S)vH!{~Irh48$KPe<;;Sz0v+ic&TkGkfw6o&N{asbT=j93m zelhH;{S)Qw%?(<BcRjXTw%_)fME#G$@)27y1mC`W`{moWOV_R)+md<N0yI$b<&ro1 zTz>96rxVKkHk%Gt-!D8a3!2Xl-B+Wlt84S^M)IA)<Fa>ZzuyIQhtHk!Q}ds9=FZMy zOV9|~r&HRi)42Fk%buK?s$KczqPykaFPFDh_ZhZ<>WS&=EhYSIzlu!tTAHPDFSh*d z(XH3xPRsxQ;eKsR<lz=hVT<2yHvfFUZhzuxc>LMV=k52qf4>|4<?Gjv8~bZ}K<P#L zqP(l1`P~xX`9F@R|2W8BcR;z{#wdfmqPEsneSVEm{nzmNqm|F+nt$kSGi+PEeqYsv zP9wSV|CZ&RkvQfj(=U?Ow|=UaChIMa?+4B()eD_$`&Jee71c3$M$t;A39FBudZXA= zdVRv*|6#wZU3JV}{}4U2G*5cA^bCW_MZz6H8%jQQ`^>gdtuFe~Kg~FS<xs?uMiaja z$5IyG*SY4Qu4CMusd@LuPVxAf#^io0wzZ8%6r8S`D6LWTHN6&b$cb-qRL_My-!5hE z`S7LK<*AUcn%v1v)Bm5@V%ckA(wFZ2JNt%7dr6&zOXHG&VDFtXl9tHcSk))|$Y)L4 zO4SK%vtr~FV^oYglV5S4ouVDf5$mq!<N3%gCyCRi;p}r`?zzs!(VO&ll>gm7;l`%} z&yVo^dAd*ieht&DHBS_N2YlIXu=i_)*+Ms-IYCRe`^y&^KK^9Q&sJG>&QTLIV#&JY zTAsxBXaT2!TbauXZ)Gm${W*)@_KN^0q|093@vnUq44SvxvTa-5X1%3PHl5acyy>*w z?WM0HvLiR8oSg8j^7C2q_W=z5KK9qAyuG#6dDpYsH#ennf4^6qADWwJH(%alE|;EG z*#<6$hX4QG|9=*J|CbnOCSY}+Zp4NLR&KEgDxBHZ)-2q-d9sS9glU$@V)y=apTgg` zdwB}5#4%LySvX1<eV?&7!J+QUf8HREE!k@eoB|GB(~Xv}&a-jUxN+mE?_m$~L%P1Y zjUst^25P(8ynlGHcv)@E=v=UFXQROs7bB<SlkQEX+TkA?`S-{t>)u+@;x%y@r<=r- zDa^eR$Ff8e8!vDudIkqvJIgjLvgE_nrRzV2*O#(Ibc#sLopq*<&F7j(ljp@lO>Ls< z_qX{49eTELhC{I9rG1sE$7L+%yZ_tJm9*1oU&xZ3`)2M4TCy!HNR!pWVYW!FP|w6A zPRYfZE6pS(D;;jojoyCY#s#0_)BKM0%sX;zozUvI=(CB&X$nngEoF~fx(;Z1KIC1< zD3<#-f7(~O$((!7cz?=u+VH=;X!c*-O`G3DyF8kGe6yr!SpoCQi4P;rNm+hb)0bYr zcS_<_m#FrRXS1@u-Qw6bJAdCyZoM51UQ0Kf{%-&EO7M4&jH88TK+C8Uxex4qzpwg& zT5sJqlfSpmhwuM&RrcQVw=!HxFW&$E_kQQIS=k<!4<0vdO*}D0GZ-{FZu#+uFld`f z*-?3m{)4f9=Y6dBrs{rXwy)m&({DoW=pX*OO@H0NL!FkIF>m7+1~jvVh+MpUd$y_5 zo}WiT|7r#*ZkoAw+7*c&vvn^IMWx9aPhS8UM{R5oU9X$|=f=k;*{=_9sechraZ+$~ zu)G>ErTbUn1*hbT6OL&lZnAQ@E-J&SxPJexDS^6YGm;I=jw)ST>5@IYj<2a9q}i-( zt?cX{_uK!USZ?<_wQp{{(BfnLs$5c$+v{v~a|O4W=BjL57^Jh<*K5`ijinn7IVf!O zS`^6f(j{I<+RIaLtvAc5N!&5Q9eymgRC2QJADZ?}NPq7ZiN(S#tcg!27+Jk9>B<z} ze|G{a&ztDGg}+)KMBB-j=<YfD(s~W=8~c9?FUG4(x}CPpX7_nVO$NrgZ=2^EmcNSu z*G1o)D^5;Qol}0VGN$mTsPnuTA3vSeFFwSnUhw<vcK)C8f0_Ah4*dD~`RDff-`f@U z^2PkBu8uvmG^n%s-OltA*JXO9YKMac%r}?5z7}g$U)^iWE^Yt!r9WsN9KZda4|(y6 zBXo*Dqv_`?pT9Xex6)?!@fF)H_DI^-DV*)D**x)Zg5WhCm#8(SB{}aBVs2Lmuqis7 z5;dPLu6b9(Slhv3wn%gLDb9y);!nK#u}r>@<yO|K?Ch7mLP5Eer5{&s>6P`?)SQ^% zoE6k!>f-o9X<}l-1TjH|$l&(b8tMnU)|3b-m`>ZeI^6i_hLa&d-G>&%?AAM!wPr&^ z;zcz_hQgI+&ewfNUiagPY0J-sD@UHZF6xoCZ`4?^cwfRy^L#xq@0~FVWAqf6TKj^f zUcH_WWN~q&Q;*n-kPDY@dzW7iGt13LKm4m#LR({Mm&hxr8@skP-`c>Y&3adQSKyAo zBDV0|9Rjz1dhzPl?f$4PQhI&c)*5DCg~-W5Zya9iU29fQJ<agu#$;(Rqs8BD)P9O< z(`H}Gz!I@7M{@q3C+agzGKIopOGV4?mR?^VyXJ31cIC^Z(|3G4CT;okO7KkMbiVz6 z-{zP9{`dOYT2N8<7}R)dlg@k4Yku#>yPf*`{}|o>|L?oyyB&`$p3f<+c(?O;+3$Vz z-^=UGGroNM_xt_&SrVJn|NQ&DKmFR8NYJvlX0yPE?8<*XpM#hEJnpyOclY(3%I9-I zO(xK4<aM#9*Vq4jeYb0#-RCpLHosmhUK786-r3pan@e6^a^&4qer&S8-N{3(+?Fqw zOa|9}kB)YiYdm^v@oeStd5@0U|1*^Tb)h{YH}~nM)B5R8PffMnd;M6i^v?hPen)Oj z<CT?_T@$hKkblO<H>OJ_ow0tl;>?W*rIh-`uK)Y<CSJX2DV(Osa#!~5mFwmS6FGDm zIVO0lIVpEyW<#Otmzy`X|C5f&$jM7P7w8`J>b3H!lg(!WwWhtiv1g`d@G;9o&Dgi` zLg5~#Qzxk`i_x1jOCp)a?L}j@_tFlg?cW_d45mGwU)^|fbK1nH@bfEr4`jSuH}|db zMJZJi^S@v2NB($MENPgxXLfWB>#?k3zB2ujw&uj_?s^$~JHU~-aMGpg*WFhII|ylY zUYr&qV%eOt(t+!c!lDVk|KF^BZ(+I0`0w{>r_kjmm3xbr7S3^G5*9PqFeAZd!_Hqf z8w@QDZhB_5@%4w~-tzT(?>*JqXJ%G@J>@o2&*57V*JdOXnJEZ#C`<^rma*id?5bCD zKL37vWs8Z2(u|1$JLIF~m;EjYf04CvUgf>-mG^X7on%W}t(pv+S2Fn>`SRt<<vWuS z5C2-brY6;N_Vu-2WWpLQZM~#_K)bg7*~)YF8=7yiTL&`7FaNeTcXG$#1+OeKfBbZ= zm8$=GBeMT#T>r6SZntjT%E-=MymDpdym@j~*4ChSx_kHT?$Z0o$NQG9UE7;@xGiyQ z>f>X*IX5;WE;r8nAM~Wi(k$o3hUSG&jtKkLxVL;eYf$&6!mUTb(b<{#?%lh4zFhL& zJ!j&dIOpJCVP*HeB}<pKE?cJ7byP`KR`#m>ZY}BS0f%>Y20nHxJkZGPxkfdBu~0}c z<kc3_z5rI0a}O^4*{afa^T#bUwRhGNJ0zB}oSwe#z?IC)7aTou{`_9MF@n4Cibdi! zRu^XZUmrM4%(s7d@tFVer7I_9aQ^=EXwy;;?TC^O|5&0fNV{qn&A5@^DR3&WS9y7{ z#PSt8j83s0@tm0Rz`JbY7LLc>*Qfvgy|m`z>G+l$+Z!z!oh!MEM0{JO*)?y-QIgy7 zwrq{*oSI*mUtC2u868-8;QMFSrttZ32Ums9Prdf$=bum0en)Qp<yn;2HgR$E$+oW& zk6-9bJ8)!*wyKc2z`02mxmJog&R96%?BtVAU*^15oG#8WJ^9879a&k?WBrnT>u(-V zx35=>da7ZPVo`K&;flS{);HI7<hIJMv6#Jf;(yip1>yPCZ`XG@s!cGD{_elyp#E{j zZuh^+>?U&7BJJ^q%Wi1<D&)7ldzZIs_wLG{Pp5zXvG4l2*xjcCi=12gYu_YWPuTzM zTUp-zzu)fex_@<b_~xpwukP;ZFXxVpjm_VAC)Sy_n%S*K&U4?o25<E;1-3<z+gjKD zyzs2?kG*?&xw!7yvlcV`eiZcO*tKtFn;BNeY8Q1ha=O`jZheiY88)?Ay}G&*2UOa2 z#V`t5U0WM*G*EqxgJEBQThK<%%9)Cboljj;n&a5PaDl_2o1sOSV-t&4^5i4YAyZV= zsiYj{(K<0nh4Y$Q=DqpOoC2r(r7II(7H`Ra^WgIH`nDUEYfdN3b&Q%HyTWMFu4PO? z&nt7ko<1{cxBTnty6T=uUPpyWTiG7n5MmK}E#k#KqieqXn>B}3#f<unG-`yOxcbz= z<w-H4*?dNhWw5mXleX~5yX_O$biSo|!nUT3T+a{fuloOf{;l<kjc<iLlni(`=L7G` z+q2EsuGnp#yJ!2~DKpGXJ2_@diVsk(-_2RScmJ_BM}M42x7&QU*!*5avhUJW3)}V! zu{a)h!@4<mllrB9cGD+0#P9mL@zm`@3j{ap+}m7}Jhwl$P$-@CW{la~dTWEFhwm>b zef2}NcG<$Eosz}rzfIR_PW8TW_4?*#Q^PZJGL~J4=nrNL%ZOR>=TBl{E&swx7MzA` zs<K`?Opg02O>xp_ohDVV=gXlYF`WpH6jq~x7d>hrT<UwRGIGv5>wUfR^R{Tq-=F6z z7O`o{cv-c4Qhur;rM@6BMR@XZ|K+Qf&+k;0K5^Cb;hcjK?Z(q`+$QrI9oeWToDz8H zp-)R^^7<yVI;JimrpH3t%E~SWze&&iU1b!tq3W(!T=mb;U1qsXLXYn;r|r1g+50rS zV!>m!gyVDeHSWA*t<9bPnzv={H@0_54pG8IuTISM|FY`g+{JDT-;F@K4W0RIOWL2e zpZXi^%xn7Q?+nv=Ge?0Rd+eT{mEHH9H%98d($WuJakrdRTaQR_cbNRRA-t!?&Rw-@ zMUeeN=7mqo%3~BC9N2H!QDf)A&ZM~@<jwMpODBGPecd?olZe2!UH&UoBRU;^)^c_l zvUPvV?F_0=cAvF=`4l$ZD9>rSwOxO|&-a(mN~wB2{n(-{PF{_h1+T{!^UnYMht-4g z*iVMc)`K%!EIbXiHEkB0x##@T)2XvGrtY3$n5=irtLpc!m-?cGYR5R+xlB7dCkFjm z<NVP5dSr5e*+DhKpKFxn>j!9l6@DV6F@4v|_v-_~Gg7{uGUZ4N{Iu40RfYW_tJC?{ z|4Cm{%@=rKbK(E<vY2vf^Ue)_t(rR@-RJwQa`=#;bDf@P#TAYRacy%~*6Z*2aLCX7 z%GCg8-uLz<X6A;8k6irUq&(o9c4>*^@rc*SGv|E%|MjC@U(rU7;?D;4(|xa6D#|#j zIj;;^b?o?$BWChnm4ZqOf4!01!k2$!<`$Q(X0Mh)!?&x=4Qij6h;Z3w9$7R+;ljKZ zo{VhGU+fj8xIOUIJjb<W?SuF4*w&gz$3?qmXK%jWH!V|R>v@JNjnDq?{!-NU=fOo2 zzU%{By<wO7yCw^0w1(KV`E#`%y>R7@$G!^(+RjGLG$~_ARPz_IuB!UA$4g6b{@I07 z9Zm~qs#<iGPAjUPcuseA<n?`xSF^7r_)OIB%sBD%#-+<=S4_;!dHZJh_T?@iI)W?q zhy7yj&;7}p?R|c^itb;dcP59P_Fg@3eYQ*4QntQxZ%*IeGSBXddXTfIDbo&dMIPsK zR<GB{&Rf5--t@|c>x{B2Ju@x(EId7W95W-|_D&L-@?~ArO4A^(DM372Sj)ELFWkA4 zv;A<yWWR?69!onOXA~@(^}$Q-knlN6?q`WYouxwA3%2iW&yo0a$N0QK<^I1KON~oS zxz>tmg)G>9*KWxa56zQLi|U@O7gAu^^(x@pgEdKCSAF%FZ#i|-Mh~Z+QV9h|r6o_N zoBwT^c{y#v2j*@A3nong=Dn#eU+6DwQSUpo-h8{+#XENzR&%uRb4y$^;!5XL(+uv^ z;z;LYIU?H5!_2g{mZeXSV<G2ZotrU@G5a`I7HLd$PEGP!IwMCR<NXbf<Im3Kyv*?b zEdKq0c#^(j`IU2XXa6f^-`dZpbYk|(#=PTS%{zJo{R&>KSij&%^`&JW<~jB<ymPhq z`DAjrMDp`FtB-bF2{;_jnRaHbtJ>s+L3)!^#AY6w_v6&68+zZ*FKIk0rm7OewaaSv z3Gq*vl@$uNTo;u(#AqcmzLvQb)x-K&$Kv=Qew{;J-CQg|Klhe=FA2PU<3L-f^o{cS zo)%LTwmN#)uRAOG`1ILBjUg7#zjyXd^b0lSE>++R=@1ZPI%({0d+<%==K`SsPN!ck z&gsH(d%oMn)m5^}|9j!?5mb0`hsNB%q{3^HEZU9FO+Qj-p?c!_Qw<aI%MtevJ@b7% z)2x^+sBMZC=P`**QG#hkEH`z|sm)+n!nE{HPQpqiBS#Ot=}Q+boLJ-B*Y`F01e@iq z-&O@m&4!cI<*G!|7hNg(eEld>{r-RdRgLVt%h@Nf=R5MYY+uC2w?_U>5!d75%k8f| zWZz)TVkyu+bnevt?{~}Z|GqX8RAS{g-(E4XN5Z;Gf#>Dx*N11dII!pJK5Mna!*>5U z_Wc}t6pu(=@JgQJ8UMUjF34lbq$%2hUK~@xGTxp(<;9tHcD}E7Huo`!Nfw79U#sVr zlwG=fyW2x%?c(;IZ!HbX);;6&dg^_UuiYhSuJX2fN40BqnRFVfm>qn`vGmc*rT&}W zPdVwKy5XGsa*=80d|y|-ny9|>#p?K@w<NM_cWk{Pw48;*fA^ZH3bi*SG!I&yDr`NL z$ou3qS4pm}(VnGzO+1An7q4G;7jcc?`MHb9Euv(G=Ud~t|L3CCn0h=tp!USba+1cv zbrY8F-adU-TiArYkI88bn_oWvzpmEzo5j5M``V{h$t|&(nY_I5?Cq(omCU9W_U@Fr zv7)^&=l1gQ+dr>t;5B91F+JhZ5>J`ZD}mNF@!J2d1swh@?<io9eNbk}ge%vt25W|Q zBs;HQKJakPVJm~HC#Cl3%#vz;`Sx{kMfB|b_ST)sZyyWabC@(kMfUfz+do<+n3!xe zs=g;vvVhZ=(TmMPbHXjb@6&H=C=^cqKG(-k>!FaNh-FWKikg@A3W1{&`_lr2R9P=I z9$*lh#`0W6$gyehjoYVR1S%U^_#_F2CABUH())DZ{Ezwb+K2B88V_)CY-WtoZuxrq zN>rne2Wyyx{bq^w%?YX|Tb``QUUgjH(xnNhM>cGHz!Io>EXr|d&@nYbl|C1V30$oT zeYGp^TG=a|yTMYhLg9dg_fm<8+(OsZ-#qY1eBR=iSNHW^Jo($d>E+{VrPD*@yBXPb z1V4Xw?&<+^<Ia$Yb<^#QUUjFW)M@xHZi`*u#_(N8CvMM<Sr_aZ%%!-)oq0|7)EgxK z(=oa!pvl_mBsW<|ej#(cv#iARwgZ-p0;le`uT|d2Df{-ViHYf>IiAW1H3nNs#nv3% z!D2Y!fZE=lj~n=PoIHKs=y)axFe#;b6j*3#vRI~_nd4_RSusFp>cxzw6QY!-xM*<( zRWv;pn!ozF%v3LzU&>w)EfbE2{rmGI_{?m3d3*PW1x8FUhwA@5;PQ+7Q$O+Kvpp-8 zdvvN;Xl^(sU%$enQA|UIGhwbv_S3s(4qY@@GqvqmSlGJAlY1<U1+<(+TrHlb{}eNt zWxz49!qxCt(j3p&wPJ}j7t0DI6;1d4l|AB@I7w*2!U^X$W*ybm{J-)2qwT5ZAD-h4 zzaXD~bLTDgd{5q%xdKOHS2S*x;!Ah?tLR+CXZl8JE8pq8EZ^@G^KZXX#I5Yslkoc5 z+BH#IyH4xxui5TzwsK*c)V<gq3EL*a$L`I=64{PgTbfinIZD`89#CX_Uj3m(T}#Qd z)k5TN?Ozs0hevywQrE7X<u1Uq)a2TaPwS>klH8nj;nJlh!)y76E4T7#2PS&FpQg9W zXD(MzK&SA6Is5!7Cbg+<U{V)#VqGBP7d7Q#hT@7Fb#sIzUULK{=+@W0DYUD<w=-gT zLZiy6g0ubqCm-gs?+ToJOyDM$M}R}l-e$|Ph9C}}iJhEtoig5fAL45%useJ{s)*Op z=%&tHS<z#C`T{MiK3k^#`)9}1TJ^}njg3*SZ%?I~VT8Izl5?wxn)<2*OBThfQeZy5 z;hEa0r(9anLed9cg-Qp1`u^{_U)Xp1!}GWQxn_Sual_5YHu}$&UObyrkQ(D)T5k0B z|Lc3_7cjh>v*z)ViQ@0pU0#`}zC!T8UKW1)KL+Y^OD^rMl`y>$a9GYofbGm2^V|0| zbS0863#EGq9Tj=SJ>!Tl-_q@?cP|aLIWSR$b7u@=_t(9(PQR8o#J@gjdBIVwcJG3f zOFMV|KEG5(dQPiXQUGJb;|-lhkM;HG&h?pX%ItqtBuZ=jFIA>Y){Psd#QLaBKCEKM z*rd@Jcxie;s}OT+HwQ~p>zD7}C$82H=n-z2a_4XRZVB7EcrhKT85WwtR`=ak?D^7u zWC81uYl_UR6EYK{r3B`6sEIAv%<(cK<J84~6^o76D9<kJkumKvUH?tsINMrh`<p7W zm+s%*F^y3y_^X;rpi2@@P-Y9CM#`rtleu>4lzjhYly^tPEbo@jjMW>ezOMF}wc-8l z&#gC|4a}ZRGrgbeu&_8Mx%{^9-o|}<8I^V@d-`0D{pG<^vN^B0ppIK!>Z9eW=4*G$ zgG}EveE+}R(DX`xGjFwK+PS&DGdLMLOYMwUS^PM?YHJt#IeUF+Z79<Lt2Li%OO{O3 zRlapAD7v}bqgV1@x})A~Wj`LP2{J#-*^`%qOT|9mSb9uy>b*U>(PsHhJ6awl-=5&L z^k*~EQ-#I4HxDfIaPZi`*E`=kXU-}qYnLn$Pa$v1bsHZ26rZ{Gf6OVjM{^#&RF_M8 zdOF+k<CMz<rxum4$+CH@EbKg_*s=D=5z#fJGj7Zd5Mqy*+PAUT<K>1^jbbWFiSuVp zKJk3k%}X0+N(L`~;NnnU&*@Q<!za}Hg-v+r1Sf$OMy)F>i4JDdmm0?Vo6T3Ay>hY4 z)K2fzIj@&aa@cwP<8yWS15sO#@7Jyt;@|ear|;CNSIGy<7M|_9?)&Y=zBi}WRWsi| zpkicbKfCp;yxgha6%Tb6xG`j}0OeTLExj@aXA~xTtXVrPC%3AZXS3v~r$#|1zC4?K z?)L_@xx6|Iofn$ct(|-2>UG5yl}_Hyk6jNBOi9R=brcXdD!T0KOuy3`5*r*cKUC_d zsm`<OE;-sYUDCEnBuaCQp@K?Kme<CG_Fgagc{!!#EKW&MO7xua{_5s)KXa{mP4Drp zS^DUt`n(4RT)Q`%+q87=T=sW$EuZx)`io-N5<S<rMg$niN-r0=Y0%B}xy5U7fy7H* z)niS@vyN!ws~N^^Ejc8p?s}|O`slQ?uAhD$&|bN5VThJsTFsAQwKGYvH{D-({I`6m zpuoXo6r|j$I+^q2bEy~aUMUM-6L#&}wTnr2t@6*qZ@()%`MsTe!{R?u-}85!o4m&{ zFMa#k@8|9Ba9+HfCUmnhU%`5Y%ajXqY<{h_{&L{@hTnn84Un`Z;V58`{7$B2a@@+* z$F}{5&M-UkV9osH)(>luEq5R9K*=8r}ErU!Bgqx7HK>KaV~9GJB2d%Lz4lhtF6R z7n~E6_73tAI5t_~(n^JM5^>e3sz2M94B2M3Sw_FS;Po@kDLq)|6-VnAmxI49=1a79 z^IlWY=u}@5^zo9n{)IbMGTBObzi#%<DZa-lu~LA`gXNr+fYI08KQ@)hRDNbVBz!l( zqlM?<LNyL2BQIf=NT*nL1!tz^C$3zbXwl5WJWI;ymfMy`a~8y`3(yK<xUg`3V9yuj zhikUFEHyIgW8@B6Fvl@fCW<BHQ{<x{r&_(kx3;dHVNoaK`RCu9)9>ayzGiy=@Qxk7 z?j#8Pn7*<xKSjv0=7!{!RCT_OGp~FI3xEevaQb-#;j|THE|Dva?P9p;)0SiR-t*=G z-H?jbg5MIoUQ2xz2K0L}PkQU%7Vjm{`uY9oXPe$w=NfgI?l__}(PL#z-TXoeX<>Cv zeVzKoduyXPog#H79y2?5lcj}~$196TcEQ$fmd#ENdsL^)QsAiJTkz!=kG4qm_574m zXEas#{(WY*e|9BUe6drfXAl2WH>XuON*^Q}EP6gDUNrlg<1<O%sObAErDB>67VLUX zneGx5MHZ>oO17N4ba~^v%;4n@<}A4puf*YeYHFR)Oo8?!2ldd*V~H|HT?$(^8(vdu zak?OXTxHq(zIAIg5?{Rbzp<lC_Pp)(oc{XsZ!Gg}6>+crJzvh}(*xPnjsHHrzMdFi z(Ra9gzNL$M{NdZKy$sg^KwWXiExl3)S8PlU@Zw96{B60nV(R&&wslsM9kn{W?;cE2 z2y^Di(3s}?_U#rv`FVD_mv_G@oBQM3YOCO7{>~8|J&qC0^VdxLv8lLfG9UBVSE1P% zc~Wi?896zB?mTo62$ylnm=mnxDfLz8_oa;z1(M5;oY|pb>*lEzVDtCJ;+h8wSnpKa z{i<{8KXcDagL9MJH77*0sNCJA(3Q0QlqBaw1-~`#8Mg>&i*huUF?D|w_MM|#m>}R{ zb}->a)SJ{J9|CjUy<=Z1VCAgZ*Wu;b6d=qdw36ALOTYDkQ2S8{`$84Jq&cQfKJ!jF z?JA`HV*Quo28HnBhxu(c9N(v3%~ks`>|Nad#g3D$@AYu(3pV}m#87-;>IUg^%i6X# zNinWj*d~>A!<nP0LGp9ja<@4DycQ4jXayThug9?h6OO2rhI7eppBQ$og*ja}cCKv- zSLOY;)9*!|J-~bC=j{AoZ((k+bE&7Vt>sWRxTMf~fU7_vC&}R2#?;4ZDUUL8B;5{w z5Oh&fGdd>iutm*`bK}QzN!g4G4{!=)ABdQwq2`&?BH*#Grl9mu#J4ZOdp0GB1|4GO zvlr2pX%w@2A-T%9ZDLbEYHiv=hM8@q(%F}a7XF_jG`Zpv`-B@=KO?L-mZV*73*Ew- zy<mTar1h@e95r{L=wIGPOS(E2>rHo-7P#ckH1V8u*XgGn@7BfL+Mbhm_gJY)VQW&p zi`wMHyO+<8nX$0;v)Hz>yhAfIdMzvKAM|JIFV3lI%oWs?TOa)U#!e}V4vu|!x2?G+ z+}r>2u#e6eSy0iQy9ipee-i-pG3};*e|r5&h2e$IX_uZ=q|Z@T4GPekzQ^i?s?(NB z94|Q+PT|s3i8?Vwp=tBJ<+%yZ)(bcNWY=?fT2%7A?022B`sJUy8ukA#yB+uSRQ8+A z=l6XP={C7)p0w7Pi#1|Sw_)eei1v+4*{l}bhJ5L~8@Fb>tY+ygbt&xe<%ykpmnUED zXt2ND<NCR^d>cDg91&fl@lDu8C4;f^vvJwn%^9+bmN>IsvMx_$5ZYp(!5PI>;x%h7 z%TpB>w#N&KUyIe%J{Fo1WMXQvaciyV<nOb47`3Kyv@8wLn#}3kQp_O|=COvg^OKs$ zLO~@5uTDiLE!PD)PlJ5y<|}&&U0V}<T6_JzIYI}%+i}KR{3~#J_q$txdvCw{axX0M zNADE}nbK9Q$?kK_pF9sdeA^k885y_qN}Zfhn5<a(oT)i0DXQX-@|2{6d->(%{#RLZ z=Fb14s1w2dG-+bu+QYT$<$q*ME;+V-0@F&B%V}p9?A$53)TB1HHqN)?fzFXamI~EN zo(DIjo;Rwy&zYdzk|?HXdQNJ~6c0t)o8AW`?fw0fJcOKuEL#|brIQ|?-ha(v%A_@Q zUqv5zb^iZ-I$p7FZ;|?vBg@{UWU~aOYzS;J5mG#u&^h^tv~G*5X0vmG&x6mrA1|6* zi?mnrYr4Xfu6sSM(scQpI;)w>s;2O0ivHGoV$@>gzB1<9(vpQ7Q`9DA9*VUJk6`6m zC~9>frK#apjVy03ug6SBP1iRvcWa|xzI(NN`|*PR%;kIZ=d7Nn`LX@#f3pmu<KHT( zvmW@JI`qba#b2UU(K6H?H0o{b01L7-7RM8Beikc)zTb9N&~@t{Yli1FCpMc-3%cq5 zARs7A_K?$$+%Mn0UAS^%MqX;d?w1zEuQPJ8Ql8zpX(t@ukR-&kcCR5zqnGSq27R6Q zb1feqd(Kgue)7i>K5nnZjcmz#ekMDJO$wS6G25^4!}A48+>|<#?;pN#|L)=Be!CNz z%jdTl*I8d{G_LsUxk}^L_tjbdljr=nccjbHL&!bpz^xfaT&8FX9;-Z*7R)N7dBO2O z{r^|j&&;!(ow+%EV!qCWD@Hvl=3JP;EvR%r!dphwW9>_QaZV%4_Y=f6WjO?TE!v{O z<2)s(B}g!B)0gj}j2fc9PqZl>Zrg59lp?M6G4H|mO>7nKfBj#ges4?f3(M`nm%jO3 zIq>%Mq2O2iX=#_)+yA*_Roq@7ct9#^#lp6`J(0y}KMy>gk`eOx!lm7d1XgCL@2PiM z`t+d#`#hbczCXQw-g8itv5mc(@_FZ%uTq*0T&*FDURh$YMFNp;pFfRCKKXpp5ziJu zPQlD0Tx>0gXS>2@+N9c><==ElZl15Hvz0kfz)5lGr{wDm0oqE!lP%npk`5%aEKZWW zX3_HTb7}t0pVLKBPJ9Sd-m8A3^690h_iswCO_G>jFEKG;u40!^4%4M&dk#hkO|CG? z5;l=a7JhW(fsBZ<vy7`v(S7C{Hwr#1Y!B*FdNupi%Ipk>3F#%#+&g1z&q*!vni+JZ zJz$c-37($FZz=|zo{NmsIt`Cal4$NtD*DNDbAyA~iA606XHqin@8~O?y?wzJ`HSD< zj<)@KYP0d@vsaHDBWvHx;RsS~%8%zg(;=hY^YfCxJV)O5ET&8m&b+2qHb`H*bLr3w z!^IPVew?v=81!6w-WJdJUti3_*FTAL@N`_b&LM^80q3KJli^)kM6&*#XXXuO@}HM> zX5Pt;hldNjl&6@xKbakM(PGP~37kxa0v3fhe4n=V$i{`aUo^Jm-Ses4H$kgGY<9$) zk1ZY?99xg>YFTqB!@;{XgiA5leWS5N`j5l!>-)P!l+}GzJaxjjF4;`~a^quh%g3w* zO0we5diZOPEowRZsKd9(q)u-`3EOiOvqlTCjE51wZ%NII-ZdrJ--2!G$p>rnH<_DU zo2>if#)eAfV72$n$_m^1YV^8$lbv1`2(1xNae6T4h^4&$V~-6Ii&PHIXgRm;EQhMb zG%X9EU#Hrh`tLtseBQ3}{iB-qtj^KX3vOrMXG|}T{dPC6==itn+tXX`_euRYIC1_$ zO&QCS=K+VU;pLhdOX7hiFMnUWd-rMn9Hu1`9=Kd(VG3Cs>+;KgQ*oT+>g+YkFNH6W znlt-eWp`~YPj>FXq#)M`U;g$jo933LJEQwDlXlB{O_9E~V{G$_+gZ~maJ95tkBdEe zMRT&?p+Ft6m8-RvSXNJRV144;8|E<S$InA*Zd}}#9(`DN!EU4evI*x4{@*PZ5LHew zOL({F=L&~kpTnfqsszpvuxu7SG(B$aL5Xfdwhw#T_W56QND??F9o{2QXMe59&|~4v zT`QaI?|ieLQ}D_2g^ygaPJ*G@qS7k{IROhqTtzl1`epv|PA#Z&GQ6bNbiw_>lGIXd zna<B@Vvl*8G7l+CmWuCE>15DZnl$t5+u4!Z-n=vssrIj1{jZ2;$F#MZ@BBP9b<6a) zv;$H5jD>!rWj&bfdMu~kaOX-Hi#Lm%%Z*I;Bwyi3;5EGxa5(SKnxC6FH!(i-^6@V> z&r}sz_=F)lx%!(zkm~tIrw_IMa`KY1J^guUl4p3hI<GJ9%W4;^lZTJbk}0|2xN=Lz z_OCx9y}gsQj|Oon%6hR{yiWhIE^_Cr&fk6x-kw5|vt~(gGJCGryKDItB_37fC@!A- z6PKf=FWo6H>10~%yZN4bveJ^}Y92UVTN8P{P<@_@d%CqRZ?DDV2`Z^A-G6!#R_;lg zcH@d}7GtZxsogVLk43o3R4<xi;r_%yxl{PDyFj%2(krLu=k1@H-2XTF)vQ^9ewB}2 zn4I&PQ)aT&BzcY6bp8M(1-;Ne9ky#Zm$<BM)YM^?v=Ym43RxNOM*Gs;ty9;^&b}BF zpz~dMic)8ijMQw6xX6v4Y@Pox<jg9)5gB>>@?CGX$-7Ka{`6iwusvN!GJu)2i@*Q3 z`~1+z!*R{Gu7Y}-SvPnk469TYAMbbM@J#mRJ{rW?{rUe3tLFLdv<ok3mph$Y<#{B6 z`Os|buBk#%Rk;Bi?Lrss-gP&d?tQpNw{F&)lv{TqO}1}YqIj8U>LedcnZviEUc7zj z$k|xP*7CIVslLIUtuu4BHJoFa;{DgeWc!cD1qySN%kC8js){D1E7*qVvU+uu#J8RE zeXCRd&C<{EYsj_yxbsg|{{FShe(j!>%6=<mNIb6*D1D$4#F>;h(Lq7h%VSBGC(8m; zC(R{aO^z;E_w+<W*HokLf6vSM+)6iEe60U_WW$f*PiaEl6T*42a}_RBM$P8BA}%H1 z7o>O0#j|B=o0D36XxQGL$EG(HGR;n7cDv?&a7UNoi4={gT~CU5j}*>a8@=tq?cJ?e z9FOC;(q-SyHV=NIzp?DF*1L+g)fS6h{W4Sfk(Q-UKhg8agNNOcGjHc>_^)hJ1l7ME z_8t3pT>kv_eP4A!=Vqpznej1C-jBClmE%x@C3o$KwLz0qx=xC}dhzlF+lpCA+wQ8S zT3zEQsGGMgh>_1*AY;jtA6_fw?_9lfe!6yx_f>62XK&lh;%6K)dqwOnpW|e|lsI?k zzJ)V`((O4~1q7^*uL@l)VV}83-HxN{XdD-BWe@8dkH;B2#~dbkJaP#%6v}4EF63w_ z*s<b>Z2b>qdCRvUv!bIbGG7+UY)N4B;#&X9qBl%xEo+qJmNO4p9JCq*#9EX$u|3u~ zCpE>GBi$pWDQw;WHb;h2{p+LuU70L0S?DvrorHTsanlW}Il?NQEv90VBcxuvTDgAx z;@!Jvf1Iq=EHGtp+!hvL)s`sb4=p#A*>*YocyqAl%9F!9iE7=aT8?x&TRQFxaud89 z`exbY<<mn~$0g@aXPn#c?VRqKdmGx;{)&uyUAt)3)$O+TCP~d$w?EW$gQm>chsx(= z7a6Zi)c810sp0qg{q~>}kJ#mFKJ2d5cpo{Z;!$Tz?boX^1qT?NH|?$b{H*YpWV%7! zpC9J6Zx6D|pHa8_$SEZy)s}Lf0krcLbY{m)^Za{!*`SkDw%@DL{{O}Q|B<8O@n=}Y zV;By&ipL%Sogbm*KhGxR_{ZrFCeQz)5*}Ciba$PMDUWU1+1aiVEq2@ey?Q!Vu3o=< zlFN-7%Pt!o*=FN#fX{^U5wCC*>jR#zU%$Ep`n=k-VEy*_+a4<a;V}PGy<|$wgA>gc zqm-t6NxX2ZVG75}6KTa)%uO%dzWMa<<fTi3R$jPz_2`<L#uKG_JWsUTlU$vWrQ_+@ z;G85Q@#n_YBfl2BG~ie<#XF|@tN+j0hx-?7+}Qc=pWU^!k*7~=R1WZ}p1#TJGw0k7 zebG8jo^!t1w)jOY`F12kNr20!@texEWwsN~u{+xTeBo^K`^@D(Zwrqnw=gz1J`skk z1xPhKSJA$OdEu1z)g^5)3;S|n8}IECYK`d#nB}Fq&T3hxhT}<-2y5PFVM4N5>rZI8 z>+zgS-=tu&aMBbl!N#&96BjSt*mzCw@WwoS^G1u~O9~&)v?x^J&-r6`^`y)O=8Lyy zO6~9#J`o+j>@V{@lxgNoUiHw!)~$8h`5&xRntZb0`P}kLSFX5BQt6SioppA$IseUX zhYeEh>?m9lyL+0~QlpgHwdMv@Uov_Ob8c<PY~Ko6MVZ`hJMG*#zj+mpI?MO0zwBq- z3)+Htr{?q7Id#8Y?yiXyU;(Z5TE27V%-U}^+vm-jSH35|LBIazX_>ko4|DGAnYny^ z-L7AMwq#!Zap$?6ySqF4^Lf>J{<dF5X7>Dde<A<>qkLvw-m`nv?^BO<i8>d_>^{`O zDg5H?+tk<B)>^NreVZMh{OZa|o!DJdK#6PjSBtD0#S)fPD#_|S%m*GAf7VIJb*fEP zmX(#=vTbY9hj-r3Wh^>{=kaOH`ETy=<HPf|V`^1ZRT5@<L^W03&b}pSo@G<lwcbf# zhGn|d;i%}1$C7$owOUJsHfStW-1fwXQFiWZ&ZR1W)0Y4LqjGtf-_i&z#|+TXG7I+! zDvDZ6e#X_c%DY5if4~l{uS<e7i~i4lm-y^UrO#|TQB~FTYh%tXIr(_wA;l>Ui~pnu zsRw=T{ubGEDAC30pI>F5r*`AiCJkO5ksqZj5zi}fk9OPqz4CZY%`bP&D^~+Ia(Y?x zY-l)OF~51n4HiWfy#f=ntsBagD$N&^P&f2^q~6zJx#XK<Q=zJxX8gCU=K|KLq!=mQ zYE2N{a(dG0)5=>HZ>*Fk6k42mVw!Gr#I`q*$7%}h?Ec_et^DJCP<*_8X=|0hhA&6M zGtS?4(R|6o)={hF%rEfw?TkAO9&fMOIa=kUUDy>bSFj*FGr6=j>~i~!<#iX|S)G)+ zr+Ckp3v_g#M{uz4R4>-GrrqNDa+luLKje;2INBvz^RYW#=F;1DnH-7{yUTRX+kU^} zcU^z?8za!+Ky|+^&*wY&FK^dNwFB|<ofd95eO<Qp%S97&^UpVu`!^OnJ*9Zl`~c{% zz002?cN8c(aez+Qs{6kC{>HSkv$SshzP5ee(W~L{XJyOp7^WQGXzVk?pfPlH*hkRL z{N=Bw#}ske|GL<}<LR{Mve$)IHar(-Q7q=4@%sJBL%VaPPK!w9XlkgjYd@Ma`N;R( zyb{(dnVdK7+dWoss&ec$5WaNv^3-V>vU~5|O(~ZAZ?|CQ&WV=X&z7v}R*#ssn{{Q- zWCo$7Ds%VV%}|kC8~N|d<}-6`*+tnR6mQ(Q=%_dSXqd9E%sEN<Eo-LO=SeSYWme>D znvg!PswpYo-d(ns#fx*xr9IoKRM~ar^anK=GzfH0;#2HZuWl$2Q{>fHKcPzWl){qv zR~9aDNcx+;;^2)LNh=S{{a<V?|Nn^OmMy&BkGDHpt<T_M4B|fIpfr^^du6uX1bvYc zPhPFi)@U*~qS91!#Xlu!OQ>CTAVW|>4pU~qw(#wH!qS!=R^wb6H1XfRI<KihJ8KxT zjcxvYNamRM=HmOCvkzKoxEuQ0d={C#eGR)($Y-&*cl(kBx<9|Vdpm&n{uPx?xwgxt ze%#&|FY(BDHK<BZYyedU4F7-E|9|h;-_FIXT+8NayvKcGt>xpdJN|yV4cZ^XzB2Va z%js#lk8h^WSDk*k@RFzc+fSwPzi%98hybmVe^bt||Nr0jAf=Jpa&9hoe!NGL`M{^A zr^_qO^VfY~2JK8#R9$54ymiTz?(D+DyygW5S;aSGU0rpzO2+h!<(ZlG?Kx(%{oZ^q zckcB$Ig44xcdc&D-B-zpOFl?81T}>yOm+6S@3ela6IZKPQ<0G3)FU@qd?p;dab&eQ z(>MDk4n3^NHIdhDNM!R~lbZ9{v)ZG(L-uZ=Wb5Or;bBJAzkG_mRyrumU9fw1dyQgu zK!v#By(J4-Ef#IbSzB<ZUEY58n@qW?4~2fVZ&M~123alANV>eNOzoYq;1W0OMsAUy zpYx73e!k+^Fu6-XwJ@xr*;~nWCreHLLZJvDCeHm)pNjkJKf26{j@}dKR=r5Ape~4u zuaWh6z%@k^3!RDG4xE#goY-Ob*wAcY%&G+`PAh{JO*s2#%`uB@Q=eUqJmooQf{LNq z$_1q!;r{#)?i)oO&r$VK+Eumd=9PU1-EY0|Ex2&Yq^D@5PkOld`I7$(H#WLhe~2-C z__Mc)`Mz7q8N*~fmG!gRKJ{ctB<)f6I-sko3pz~K=J%V;phF!%C-&+@ZRyYqUiRUV zxBlA?za)**3=$8q{QI)pK2UEu``TVP+gU$9KL>5syL|7SpWXcQhlg6<?0&zG!Dp69 zr*fYKQ^WN5x|yY~uZ7;%UYc@hisqTQ*3+j=6Pu<Vf9}#!@0V}h+<7RGc6Qd$4ngG| zuh;DsaN3Y?kcrRgg#zd>;<elFd5KiAhY7IARKM8>Iv9BQ{JL4k<*IvBZvM=le0jM) z$i6LGwrt3|YxVEXbNkP)R<94co_>Db*$s(@87@SHpMU(-;Mj*F!u|nTQ_CV|n`8=s znlYdg#g<Nw1D)nqcX`r}NvhtUWBN`%I@-PSVViVW1b<V*WPdx!WS>w&8T&dLZZVyN zD=PwZqPO)dpI6njZ{I%Id(~eqx^GTA%r>w3oh8Wqf$p+Le|>%Z^XvNhUc)v{VKsy7 zYdUgOFBGk;tyivIo&5jr_w-X!G#PrNOtY5HcU~Iw@S?l?TC=+R{>aT~hV}nyq@<-I zca>=J+k9{^wdelhn{;na<(c{R^LOpC3R@p{Ho4#S*srgzSFexUQINQG`}%e3@}^%` z>PwcZ{c>?`+~;lE%$}W_d-}@C;MJ?%oz~yK=kV)Uvu0U5nc!UU<)Zt`7cUm9UE8bN zZ!<}OqvFX#_p<7lyV?2$7rPnc-HFJl683p~aZi`YgZBp}a+-Q+o;s@Z^H<ddPQPD8 z@6EQdP6<+wIc8aOQ|6deSFLMQ`&Pv%;s2kVnR|Le;NiVhGp2bjoshs2rY4a*fn&~8 z7d^G<Cxs;s%fH_-_kZcF<C@1(*KE#o@tV19;^Dok)J*(-ZCWM3Hb*_xZb8(>tgGBM zKMp9*DSr3-goshZ>$6hc^P`VV`TOnYk|$>)8kIwzw>Wvl3r+LlowHKC_2r&K-OF_j z2Rs;$1<pVD`Sk3(q<?#M_S{WxdcR$G-~0fJ{DO&I%UMhFy#$>EGaQqYXGKY!O#56? zo|AND#>F);A7!3)DRP)R4Qlmqb9&{n&0&(t%R5h(tlDIiZK&m9(Hk`BU(m#5YR9jg zlarF--m~eG>aAPHjCU~ndZ#3vmF7R+ab?J}hrR#p?@rx%`_wLG*68hP-$d)aT$Y-+ zajn&#U8SpDz4-Q;d3_<D+BNwDbFMuudwlb%fk=hFz=6yD_Hzw*c78l2?K!Chyif1n z=lRb;=k7l0*1z}g>-4xP&EvA=GVXGfD&OxEpI@*QwEZup=%i}R+wAzqpq<*_)AoKo zo6Wwq{@3OCY!BM)|0u@)Xqvv^`|W&t(B6v81rHB7-hTb^<-<Rp&p&@||NrNL=b*Y4 zbh5KspUg>L^SehLw#&!GR)0JyZux4(;*5-p2jTmFiC$jrzkc1_;`6q1icV>kl$M6h zpKV`n7am(G`uX{J`7Qk_o<F{A-w!@HmHET&`+xg7h1Hn?;^WWH|Mz8iY~8ZwbBg({ z#}xa1Ewr2e{QkeU_bvYa`OMC15x+G{bosn0Eq~juSM;`*9_BUwF!y~;JAds9XA?8C zOLy<uX4EeDQ~i8y`KHp>Vf+67eP8^rRh+Nt>@wfkKYkpyKX<qMer&DY^wWjMWy=dd zM>K*iLzz7P56jxW;bq_6+yv!EP=oT%-~0b<)903ofp&s`!fCaNFkAfj>&XufwKo4! zaPN~j>0kFr*w5zU5y$n_Z#EwPal+m1(6L@=%U>@R|NPirf2Qs?Z=Z>VSa;1s?)V3* zR<CpNI(eAi{!RXaAMeje$9D7AeQ0jJcG%!a{J*F1KR!+0zo)sX;_uh%#Rpl%FWkNz zUHfjw<G$pRlT>To70*|mf4=zT(&=H}-_Ciw`~F|O`#+AEm+ky7b<eWNAmLk+<qrcP z=A74^lf1&7f9C6m=JoY0Da%m|e}7x;2t%}tLe#ZIm)`GUo+UL~<J-538!Lq$AA8%) zDkUvF)3lz?FJjJzgC~wzEcv!7QHMuTG$E;Z0++hzO@k%Nx3ecXZd=%3Qo+9FQpwjZ z2G!4ePEAz`V&Q20uPk#;a}BFD&)m1sKQ7<>Uiji*`=uK(2X>s8Y^@l%J<ry7nXjWq z@6jcCsm)?_Wg8Am@3hq{v&&;^=TJGf^x%a<N=x;Zr-vL+=C^f`37=7a!Da(fbGhSh z{%{4sc`nQ5$4=VSHFtAn+d?G{m19vUGRjNTJas&iR<XEw_%^6ai`!e&c{IXXBy>aP zLJ`d+dcs{idZlsd%Y1T9iToChi{3ejUx(?)ZvQ{q4sI9!vU97>+aE^{1UFazUr|-N ziYNcUbb<d<@0iu5RV%%?bbZ3AWw$3Ea7eMJ`{TO%{gx~Vqdn@c<}yFM$5{IEm~=kN z1JF)L>3#lt4#ppA+`9YSuI|m}?PkaSIrN|PC+KAH<#t~+?Y^$`FFYz5&aiLJk0+D; zHx)c|s{1r~{)dJ9wH?ZR7EPetx=%h=)_vPNzwp({<?l-DL5ov_)%~7$$Nv&qKDSKj zy#0Th;N^Z#k4fi0xmW$(mE&OL^SQ?#9qo?XnkDKkQ^*qk_f<H1?&CSd=N4|=I(2=` zQ*D`w2aRXuSWYfJZ#z9{;|bO2F+r+JLHAevyt3SmwZh4$K<@T`$rsh!O$it5>V6!S z|5RT8y&TlJIod5={NrJJ@kLkhiRYhNe!pYB?Zf_Wx3WPe5w|3s&|E%e)8Sv=p56zY z>&>mdX98#sp-#+>37x{~MdvJ^PdJ(K<FNd{fY7Av$9p7=f2{xiOCNL_joyw2OnUqO z6y3UgySz#Vbes<89<lvD&*nEAyk7j^yhEe~&*4|UTLk`m+rIzl5n=x)+ivGQUNYJ5 z(Tm0X&#LeLmfM_ue%-X~`g=Y&Ez)?j=kvM84a|HA=jK?}y!4J&;s6_dtXH~y>om~X z|EsTeRDFFlH?Es8=<l!WjVULE_WioL{?nh&=ZlX?rf<l&sC3TqxlCNmM_15F+PSON zF#P|(|NlV!pX2o(HqZatGuh9o6SNuVNa305`~Q{pS-n~j8-GCRo?+VA`L1U3zg`V{ zczC+%s$1euU2cW9nTKU8y^!dUAO3#ZJx%ou=L|pC&;R(`m$!8nQ*3PX%eSx8XY)>Q zD!h=`E|Ae%z;@q|y{+ZQ5f70|ky9pGEG*1Sj}LZM{{H`?9pC@iizhTXwJ|2DIqOYd z7}ArGk*8F)FQsSN1DRtEQ&e20b|lqLjQ{uOx{lQYW}lf>GmnHBs4aXXGqo%6@vl;! zd-+bU?tEnlu<R@lQ#5h%=qXOnaf}j@*Km}cIB)ZT{<Fe;qWXJ|H1pdYIDXDTRy2*n zn9)m1gl{d6SM#-bOIA22Y<1F{+IRPIgtYJzk;QI(E?sOQqD!vKI1;2eEg*A$qS~2d zswMHirUnVIFggk>FqT|$Y69n{jHN3>v^)|Wq?snVvh_{XzW(^zqQZiWre8#>4a}bP zYyX#*N!uN_ckY*e8&_}2|MlecsYA_k_OE}<Yg2N?(j@&D-(SzG22XCh7CqoOSuON* zG_!5=_q*ltplciE*M56A!I|&jL3a5+-P`Zqym_+pdaQeNwDj`%bylF0aj(Z!zg=)W zrsm_(D_5_6{QJJXeuC$dd)4osUJZ|bdMkVVQ}Ahmf8XX`E_Az{u=eSO!+fi!O`2c* z&N8mzAuFHlmw<Vd&m{Y7KAl+QT=Mu>@15fFwl#kq%gZmh0j?0AYR5~4bk+X*`5d%k z4RkWF<+B;d6@NY+-}$)DTEMB`tm*ZDl_6yo{2#I&86KB0ez6lYGWG3d`sI7~&Vg#c z(iiv2@7KoE|NYt{W%|n3{<y05w1N|g?HejSK63mmtMNZfOEhdv#KF+;*rT8mZ{6*G zUCfI7IxBnK!Kl-qE!yV$KJuQkd_KqV_B@M1CD5%#$7PCn3T5^`EG#K0DY#pD-LURY zg`efqDRbk_8=to+p74t6-}Fw`Zn2Lil=}-Vd8&u5e+=614GOyYdV2=YH4QiRRDNFY z`p=uq=QkxBWIAW@n1|2$jlndX$V2&cpQY7&XC2x9|M&jQsi&vSjq48fvrJ_V{eFO% z|H+oie#vKNnaWhXSQu*h_2Y5*=jHo<%Yuq1^*IGh?XqPO-|yG|U+~>;mPzONx^J67 zo7WjYXK|-&j?~-tBk7#YXP<YwUavF%^Cs)ZX@jCK9>;p*ABWm~*jfJaZkX5Glk=x! zriWNP^Kr<|)_yB(HgWywJns<Uf9lyfQJQ=DGB}xiH*WV(n|#>f^p>5*nOV6jkDZBN zcd9tFSao0fdCmBH#e8cVPP9Bc-1hm5uz%5^mCFUyC!TkhCNNdG#rs5xiD<HbmV<U@ zP{J10#S;>&-$uod1r|XTI@VuOyB+M^-T;vTBE|OS<yHa7q%l7E}60ix%I2A7`A_ zs0z+<`RS1Je9s|`Rz(4>$x(s2lit0H%iH@l%<kt*|K+Oj{ui9y8mx4T%w}}^RlHR& z$TCG^q922xlhvoMl|`*KMiY4Q^VH%`1i#S?>`ZRz`Pvf1X|H(HQ^=&#mt$%F<cUs` zCUUJb<#QAYJ<-BgsHwDAdcvim8xQ3l+~sO6%Ue+H->{(}<>;(lo$8NeZttU)?foGW zy0yPiNH0I0x90Gs4fV;<bw=#HKYqNkxhvHsP`#JwN7YyUKjL)@&X`|Gn{eHk<KWEn zd7Z_5?`z*zTd&cN+|;r*db?5St1EL?g+HHDd~Si=A@TT{iM-Ng4D&j2<oS#K|NWla zllbPw#;Zbd6+xRf+wFNizh17P@bSG!mV+CQ%XLqg^m^Uyy!MJ|zO&8tsvbU}U-yxF zlFGvsi~Cl6Q#`co)BCmC?}3h$Z5L?LUcaX(z+X0?^w7S2NB9D?rdoVHV|;(gpS{8| z<#XPL|Gd~=w}rVgeqW8{>hSe!HlFo=t$6NkwRpW|GsBOM{q=jCHET~#)4jT%9dtSn z-}}9wqeh<OGcfZ#*_fQYf8u*Smc#>Zn4cx&S~WK1n!DSpovjc(d&}hed1p`gKQSw` zFWkP}zsB#)jcY#oOPS`Z4~uX&o4$DI*4DOXY|nIOMDP76Wj}|x(SftIVA7G9A-TqO z88_8DczVC~o|$DTT#)&H^?ueb-@gT(5IYdDrFdSBq<0dJXU+r*xqa^$Uw!tKDY&2% z6ICSYv}mgekEwR}zEeLsg*OH*Wa_=37}TcX>9jKD2uJtPM{C~unshRHn{o?0_sH>T z75?#6zy9b)^?42p_wkt?2)p!Y!xV)j2c!!86sFAgcw}!qx$o%YjHLoz0X@Gmb8?p5 zxb7Z(TjM~yFv}FJsaL)<_3tS>$L_-Y$1v$~(GHahvot&>SUJn6T1>xiKlahV-|{!! zoqAvC5_qO7bamwIeS!@|@h;*1`u$t~^GF2z_Nc#iZ|CoGR}bXA{@=dWynpj*t<C%Q zSHCYlC!4iSW$MD9nVw9XoSzjKnRq>Bgoqr?%gC&M+mO`FTy}Z=wqL>*w{4AoyY03c zqaaIazyr~g5XMvv77hW0&o+}*dG(fCr1QU*|9!<*Yh?=qr_1kk=a&bqtUhP^-6ypC z?pK>^+osLOVmn3H_pA$X?PC7t6<c!AH6mME^%mowN8<Y*e4hW`26R@5cIwW*jn}S) z744LnZJwX@`PtdsI{uSd!s9AiEsLKOTySK6o8+Y_!nNCG`R2`&FD`a}zv)brcX+t? z;Wl37>8IZ&b<Hrz6e@mpX5reky$=t!hyS`zrl+_skVoM9LYd9g-QT{IfqKo)&dxsm z`~LsBbvvI)B^3PpzW)EMdZRs{lWE^>x!iW=TtMTc*x1-L(c9nozQ29%LGQd~XMWo$ zi~H?nZQEuhB`t0F>4b9Q_Bvg*buYQ~_ZU3+#Avjym|uyfc0F&3qnWAc-lcz6C1sqk zc@tnX^Tg_~vfaDV=ek<lfBtOq%N$qtjprWvG)+=0<t@#*vt#0~T~bT94*V1>I2O_5 z@RL(E^Zd-hX}{Xo`sP<NH3~#LJu7mK$K*@)6akMZ`tDZpEN|C1dp2&KHeG!0iIeIw z{hp!norfci?<$=waqUh^DH|t?=u-DbYZ8B6TB=j|HT2)J{QqqREX((<dg*H0J%KSh zOfUW1?mlI%y{|M|l-IHfw_N&ula(uzm(fn;HrM+*U+?%avdL!G6@SmSthi;O=0Dfx zq^d;j#vnxl6{{6K=7K??Cl>lENmksM{z$d!#*|E1^R}e)iC1r%86>%IpPuftNH<aB z!u@ciGtU=_FA2$*ogh3{tC=g8$0?F&HRqxRA2p{`W0j*b7MLkqY~z(S+njmXD(bjj zgRIEb?aWRbi+tLyZ428~wf*ANyT0k~(_ZmaP5rlN9gn79(t_gr-BKJpNB+EB!1ilt zeh9D4s;5lHuAI41&mMKu?l_|_L%-dxjAedvz5M<8@Bg~Cy(}`XXW`DBGePz9_q*lq zr`JjZ_*q$5mF+%vVAHW<dpGZSzou^Qy-jUxY<c_tmigKLEm^ZQ=jNu?dGq96y?XWS z)z>(F=HnJqX8-JcFfBSS@!p=wnitOUk7i}BTREk^x~gi&_j}dawuQR7x+$A)#?G^^ z|M$msmhU(9Z{K9LY~5P;d~SKslZoz0J&Bi>`F{ES{qmhVd;Gs8E9^^K@!*B5{QcY2 zxejaZ1l#9`=JTCBJUdhN_ABqX*Z#lbdd@lZsN&oMJ40p)T{?fX)nwMu_3!5_T&Ct< zU9EoDjpuMwJ6Da}f+_cQG<?-c@XzOOm$A7jY|40T#+EOygOodta5=xw@sn)vUEZzH zxVbCHa@pR!bI;|jzo>NlVTl*R(gpjs_Zv()a_&Kk(zaO_*dkWHeEs&}!TWXx;{U&m zpM18BW3m88<3u6Vy@4rbKbiJOS$5Uv?T?LhTJrE(o!AB?pSxSdv~`qxLj7NVRqs?0 z5cL21lC$U9oQhL2^0LV)UM(*|T&H@RiV}XHoRq}lrP=ajqkhn@$WuxmE_<gun0h5> zWrJv+f$+i*55tdw`ZF~SNj3*x`kb#Rpb@|C*wU^Qu1h}}6s}o$Q0TbSW1Y^jDW}@D zz7AW;@?ox{SwK&oRNpqX$j!6P9(~?0_td^6-%s<glrHc-p#S;4w%>y<mDa)sxdMHB zm9_?QtM~tWQfIwQ>l;5`22;hyqvFi>c&$P{Y~CuiR75<!=A#0Wg}~d5$&>%jKI*XL z_&kv*6P4YWc)C(<PXF=Jzy8$A<@3+||8xHThpFppTEBfOJK+Ct$KyWhd!N3sPdPhn z+O+Lk=7KtaP74p5RG)w5#l^*zZ#Epx$jW-uCY`q+L~CQ+->N>_ZxNt-J5uMr`M&SS zv$L}^b90w2U7Ff|{o}jc@1K1*%>O(){<jq9vMepFx8nOgu<rYP_x--7e{XEb6mFL( zI+4eD@87=bt8Q4g1fJL;*}fnsxLI1E`~j!*yeW>WCUE-yiAimkeIP2oY{lBMfiK>x zdzu8X-jkYm%IIFif(vfJ!O{KK`W!rjgcm0}s?E--)RX<cOnA$w1w9`WuUuOYyy(jn zVgI5>oa&obCNmrB+;h}sStug%`?sWN6^nq7mV;)Cz!A@h(RF3U?=9cgypopg%#{j% zqQcZ(=#Uh-xyW?!@t!X%r#-i9-skdKB`9kOPw=CME1OH$vXuqIq&;#h9lJZWo(|ja z;Ai^JC(G@fPfBg_5)w#C@o{L`!0Bblw6Z3o*O!As&`F3}zCzbT<<R+Gt`hPG7prXj z8MUU-K=YwXhsUWSs=mIt(~ejy@lfxK*l<lDK*GVR{;0^I-Tkf(J1_K`@;w$Ri44;C zzPa*s)V9}&`T8s?rLS9h74qwUi(!8F;OU0B9PfIiEIi(N&)>fL#EkO(-Ax`(zaL*1 zx>3IHz&8dq#{=zlUlivQgT|9{%yyr?zOY@6D`&otQA49(A#?sT>!e3VI-U33W5~Qy zISVub+xd9L#l`OYHy>ZWbLY&O$jt`FHl&=KWM00Z+Cjv1PUW+iB3!I?e_#5CpSb_- z!KFZtoiTaqo!7FTF+DEx`I_4|(D6#M@Bd-bR27dYIH>pVymr_c28p7)_tw3Q#RYFR z9)DLhcVqJLq8|_2H&=X2+V}74dj6TwJCw`H{oisjAIUp6$I@BP{^^uphBE7yOS`tS z8>gRLv~go!(aM(jan=D%U!KN4{xkbE!^Fvc3B7mMeTa@<^d;qR;QcE{w)OdK*thWf ztt}~Y{McW<e*JvQWxu0oB2L~d+oh|^^Hon@((b$V>$=Ix#ip9lQ#R|we&K4DwVb_f zonCyMso^zAnQ8lW9QlxV)+4jv($BZaKfbOlFZlCO-JtGM#UTeJ*ABr;!mOHsS`M8P zL{CpE{;+U!&HW^=hL4##9D)KIod$gBtYI8Nxf755dMmLZ?85cEz4!lp+a6PN^8TWx zE0M2i+~f~E%4xc`a)Or4!Ml0eCbA@YsGSjHQC!IN_q&2hK-aBbHfACn0RhqCO#vC% zou^gjZ1s2^kZHfTZOfN;`WZ2LmoMM<5BE2}z3X<NL`e?k5~gnTCr?}c&Aa#I{rlVH z^6xmF%RDXW{5iXh#nJwd<q^M@lHJAAxBSoVcxr93iSO0lW<};D%T4DVnsQ9|``yNn zkJ}zLsDfvpK<99MJR-a%et+GGQc#Df_`I#V+T@4K@;@A&er$Yjo4@|Y;byOR(2(Zz zn4*&tZc8bIZB9EY^<~G_Y0~+71Ql68wGrFb3Qx_S-?s1fwVVGObUknG&39`ZI2<L~ zo)lRg>z9wO+_P;PcratP?X(=TXin!k+dsdq?>`oG8nklZ&CSj1y4H_-jDH*w-?!oV zZ)=Bddb?gI-TQs-`=->>)4aCbKWl!!XX`X?{k<g@Hu5-VZashMR=x;x*OTWWUB5oS z)&ki7uXO8`GR?So|Nr0npZ|T|zu(Av$J({I0xP90i&B>EFLdXr5dhtV^YhQWS}VB| zX@8EW+a27Jd6`Yu`sI?zJ03J~XXNKU|MhzP{nN^;lj0YrhHxj}zUAQHAFm(8@rEJO z`{eWwMsoLZ76d;EU%CG0_lSqFo6d1AGGI{Lv++PhaEtHn=NtMIgp1Ayx?i-al-V0= z%Q1ab#xWtQg1m&5$bi76HKGbN{dX>fixr=^GINK+h0B+_H?S?=`zUqog5}F+x3#5B zIwE}CfTQBi#^V!=4o^HT^YphAW3!7_d>*fihGOLII%efr(ks@k|G4<=lrQH}Sp0tM zpR5&XwzN>=^=1a)*$Qi&BiN%pb<e+hXy@}ezPYt_yqmXWUf6sv;?It)Cil+^$21o+ z-m2>LvO1t9k-kUJ<=1m17O#UZrio>Js?6GK`RbL_#&hW_)jWFwn0jyL$vIXUsbAWE z(CJ4(_VZ%)$vb+cOuWCZN#V?=SK8gdhyI^is9ZO7di?HUfs40ia`5#Pd{p^xc9x4$ z=;6%V>i_=&jyAS3Ph;TQQC-gSRhEl+-3i&d2d>9e>mE&-Xnfvga=U!p4A6mysSgje z{<&=bR~WQacf#$;PbbwkUMu=`Grjox-SW@*|G(weJTsop_~*@yzCJ$C*xS6iUzz*9 zuFd}lx-bzma1A=TFBvpx{&jWyUGet4+^3!vsos0~?RNh2Pp9>tgYJxexqSXQ3I4KU z4m#&R*BOB(zvq_U+v#3>=(PU+Grs0`UDPH&?63c$d_A^YHax!86m+az#e+unGDW58 zLw~>D_fJn(cbBg<@%8n+Q}uf7RJ$#p?j`8PGZS<3%>@sgK%?-VSNhj>)&FR(f8cKa zOAvJ0Pj~#EN75G7zxlS`Et3XaSp4`{Z}Pz=);}NG?Vo_gxVgpko~YaZ<Xr6DpZ4_B z)IEPboxXDAO2K*C?*%WHPXF|Eef`|@d6j7%pS>0aBs@IS>Y-Wr?PfaYkm--RjAzWR z`Q(|m^Qo9ykHkUHi9V&*V~>l5#~kc6zjwl!-?pW=545#Xe0!N_KK~(ulw)sZzTCp; zD9|>ATlN33`E3h%S2#3XVM%0AynHc7%;xRknQv|P3%Mr;GvAGk&6vDk$)}wq9Ix6< zAGIu8w{l{$ns4gORiPYADOO46c5L}C(0xddi!(}LtMlUxDmoQ^GW%@4S@aYfSt>EN zZ+5W8ga;)~Q+f-+l-54{`FvjDMep^W4)WJGB*h$Aw(z7=M9W5r#}|$z<R1F;R69fV zde^m1^&E~hU;fs6v3RInWSa9OvqZ1JPD-6YyEgJ``Tp7ohx@IXIwz|wFK!TJdb+an z>*u;w0gLQy^Q|A&yjv7fSJm<P)Cvz#r}UiGlR39GO+1$?J;CKm&g<oN@(rc;dUJ$( zOk1>?&H8#uGtxO*SRPLB5_FMl@|mV_N|04COqxkkLw%OUsR`Vy$;bNKJwI;ye*4#^ z{2s$pxu}0<Pd#q_rli_rofN)kJNwoRpFSs;7UaE7z2bIw<)ib$>?!;Urc442PY10u z$?!TJ@Z+g|{Yg*~>r|iTQCn+kYikQ?dV>!92aO)hsd}{%gmoe}wN!q7CfKI<`Ptdq zs$r=wFD(U)06)5Y|6iHvm+}K!HY6Tq0}bod{dp{3{OjfNaIYD+x8*+m^?E%hVauD$ zWL)7gjYl+gk_zX!or=?^o=)vCY<8Pc`(?2_c)ak<=JU@^DEF&)3ccI?-VW3;Tot;y z?B+R861lQ6*z(B)=N+F;Y2VyYnB3aJyJKm&-M_}0JLdns^IXfa=4jGH&?q}-(5reE zOS8anL(s0>>9J*!$0YLhd_3lOT7UN&BhVx+Xgr#47F&>pNX3(h?mxb+uaB)fWBH%G z%AfE3-MP>2%0BOV{cgt@%j0);7XR%3|ASv|&j%+^LxTCARQ>PU_n(2zn>uHC@BhE= z#h?+u@^>-M&dv4S81dv<bpF%*|6cE}cs4V=>}J1z%_HGIufq2y{rd8<=I817w10no zuHW4cx@b~=&j+UPm_pa5Q7WE?4z+Uce6#6v#jlskzrT`c2)8IJUmyDMSmB2?k}WfN z#MWPU`pMGAQnANqpFH2C9pbaUg?rwQ)W1};PGW;E*Zl(hnv>V8I)fCoI9|Sb<;XQP z&%5x-$M(-RnqAjy;K|Q=^wC`|`PmxDm)4sOMKm8$Tzc5UBj(NLk3s^+0$=DV#dzd8 z>+bbroTDTps9IyY^+vqX{F6a`LM<(4rMGWL`1g6w^S$B=E@#SKvuydQCGn$Twu9H2 z;5Csuo4)TYm-CY@kt)(%<9L!`vWiEedQ)b^*3xUoMILSbJFl{cv9>ktUiqWyzxUl# zHyl!!!ouEYa$}3V|FR=jt!J=yZuL+W3`(5(`J=%P8P{yxnRA{jeIEB@-tG5Emwt4b zT;F;z{*A)?)4x9DEvnUD*ytk?q*ZbCyl1np;6fn}RRJ+4)f23WZX9cvn_F2<c{+v1 zH`e&BRezK({r~e@yTV10d-FtBdzW7dj_dW98eTu0cg@UyZ!Ym`TF-X4H1*pJ=@Si} zN6P<gy(V|;jo@y!|KT5>H=o*Sf5G5^(A~;u?*mReEz(%p_U5FNaT-t1DaX_&ZEb8- zRaI>zcb<K&Jk~3Hd|U2qEkP-3C(WZrI)ytQ@0i4EE^^2~W%5a$o&JF$f^CVaF%|A9 zn<JM@adxXRF*7qNdlNBDKR(V<e`ideMPK>JWx`GdX=fy|va=&MCb_0wTQg<Su3fug zjh>YqY2g&sIxn3S_u<}xef#FAcz*lw=hv?)HQ!k-<>ltt*VoA!#p};MpS<?&+u9Ag z9}7B#*a^I;nftvY_dxt(&ERDUEeSU_r8>X6-XW-*k(rtJ^3qb#qN(SfYl?O6-ZL+# zYuh%nCWVBjr>2S)$+Ix-jLDnM&u^Xd<HN%q8Ouqjr>DK0$YE|`a^d=Q^C$bRUAZzr z<z!vA*RT6cfyr)#S3bH|FJCw1$gSxr-FyFDxo#eC&2VDZg-lDa4?pWQepOYiSe@<A zHg5-qpaAQ__m@TaG)0bO^lSv3^j4#G`o+h!XXcnrZcF@{6T7`P`I(IGq$7VmiEl4D z>8`gZ;GH_pD-Rz|Rb8zKDz|2fPZ3hFa@08ZUao3J^Kt+5J6AMCN@vcG{VZ%(dQ-jA z^hwBxQ@pDyN-v(CQ}j#oh+FaNuja*10*@QiUgHVi%Qoo}P!v5TIYsD*m7=zDSL)f^ z{eLXw{~!6kQ0BOXq(F<}(IpL&EY}!%n0P%gG;;LvoTS3Smm+atW3IOO-zRByUw57t z;OGqLauF$Dk$Afz&@|#=yC74pLxiV9ON5EXg=<1PI}|uJ9x@k+N)`-T@OVc0ys94d zca;s5&*z+7;<-7(qF!<C`nAi~&-id@QESV@q$?`~A2_8<Sh#qvaJ!lzYs*;$0}fS= zW}TZpE^5;cKj`Q-yjdfsxFGdN!3INRce9Vp@_#18Z2OlR%s97nP1JU=#c_`tzs^6n ztC7DdX?o17x%c1R5%?Vux%|>vg|b*ZhpvYHGdpG`?p#>?YW0uL2N+i}9J(jCpYcs+ z3eS#;@+0$3_%94d`1t7P?%2GZm0u*@ae7XA6IR;!xMF+$v1+S#>(;GvG;T`#e*E1W zX%PoohU~X;{qleQ+~3}{S2OV2moIzrPJ9V)sc?Vuu3}E{ZrgLVvC;|ad2FM%=dJzn zWAD9vQps&L%cEY~PO|^-ch36sKaIBcFFV&>Sn;S=k%Ku+u55++`+bf2v5z>66^}Yi zG!Xw8lpnQj%AxOJCmSElYIbOKIki1G;<?6DZVR4;JcfRYLp+>=nN`{Z54RUT;#4oZ z@BIDKI%WSwsYeV>wYIDbUMAStuprN3r-pm{LiX2d=I`xx=;S$++0)HAQKz<4GyRM$ zvnJ~$r`TFuiQYb4E9DnAZh7iWXV0vB@{fI{MIqN_zS+KSCYfw<Q(AgtS7V*q%x@A_ zVs_tk9v|QSaLu8Nho^TPo9$7fznHDXeD;!`9Xl9WT(ggVwcpq0U-!mn%U5B`n!=cb zt<LIF+NORQYfL?~Yb5V#guM8Bu`wXxp+}D@hl)n$gr=hM#`*F8g9X~^_r3Zr<T7cU zp6^1L$1Ms|E(v?QwU=;BbXZX1Df@g|y5=&WPJzB787@M?EsRmw@k(qya}3t3Y|NSQ zbfx<LBbvqMZ>{{dtNy_p<%_d|V$u@d^B3sdbi7!YIse}5aOS<z6)#TANOq48QmwCN zv`DCCSiNFVmlmH$PoC`C=kMML^q5WX6i+d-cwYRbrqRgPt5_k`L%@YaOCf|YP=axr z(Mcx_`42fCYSU9=m(BQc@$&7n2RARjd~xs0>G5@<i+@Gztu%dWyWVh3u1NQEJ>`P7 zB{!T!I9?f9N)>PI$&xwOk*K@Hq-Q~Higfn0wMp*^>s@POWw!?Q<*aMFwM_8E4J9T< zrwf-ayT>}qex6@3Z=c=aIhXwoPEy!lx9e!5=%N1m6Zn>>2sCL3Zz??OrshA-XH9Q^ zu~<T>R7Wqfdf~PH;No)%J+4B{!hb$J-~ZstWq;-H`Cp&=E{p6u_MJg%Wx=6I65X2{ zxHtHPcx+?ISu^pPfLFX3-;yU&)8{{JxBuavCReH=|M$vqMGnJT7b2!7N7M>?CP{>a zw>u=RRp{(BpB~{X!FKP)!EgWU6>VmkMyzSpIP*9_B6dm4tD{k;Pnl-FeDf~#>aEay z<{xt#-aCrE*fsry&R(k(;rZ67#c%dl=PxraIR5WI;?0jT*3Tx@mdS+fDYi%uJ)pH} z#iA}|#>H;^k1iZe-&}OGNX>7~1LwJtGJV-=z9kx*TNt!FN1{bTQbD$4=|=;m_TYW$ z7ml+m+gYJxS`yJ+)R&l>{Nm2Gsn0GR?qphDWSOqveSAZpuTI4S!&}R?1nPW$=+x@r zKCN+y-5T|6tSklJ^Xtw&ogVLaQ=}uLuSP@is)<mhjPmSgo0*flmh3*D-7WTU=jr_o z9L{sRU-)-rW+gVc{7R5`o*cTy?8`T?jQe|L7Un+Qcxke0a?ScVrH7>5S`M85w$<YK zRm-I!{kESZzHY5tCTk?D{O5~cw(d2_77>ey57xXFJmNKH14njkhY8<gi75wGx7|`o zaq_R`-@ofI-yFl3x}VP{NV+C@N31>Qq$fXV^~sAyH4+Oaq#TO+#Vs50dU4#Qn=&4a zT+EZ2)*rEWUM$Wlu&W_Ji-%2B_n2CS@&z+Ro=-<MF58^^`nKY~&;YMpGxtBU_psK| zwya~`{>(0zd7+R(?XMPX&L`35Z>)VZ*L^BOSfHzD=o_{~38U91B0W@RT4V}IUthmG zH%EG9NmH?yqN-NFi%n|r(XV}(ld4y&6J9Vye|FycwO*UQ$yDfihg_MKV|KoC`J5AN zzOOT5wohC+d3mszl&IGRHrE4PzOQGxI|RCU%ziK>{Nx-~ZJE^B8;YKKEt4^s+jMn` z7w5um&zz=ip6qSwmfCl4E_FJd`po{fj`-iV?Vct2*M3aOkDc*#qW;38D-ZZT6<~VI z<2mWWmC5G~K2MOm@>HtBQ)8w?qXP$P*n*~pAR%E3-xWnKjwA%GiQCweK7ZEv=l?zy zdF|>cnOGib-Cd-3ZCZhofQP@z+KU|rDkr_vIV5EurhFj6QA6gu-R1^%`G2y@&&)l2 z@wjZipUE*bi$5kJs-j1WW-gn?7Pej^aB`@L8SnD-`<q?VpJacwQ0FjKtYy8wI-}=c zr1!}zoj!$5&99=Jiv$E)C6o(NIwl(hxg-e1-QL2Q%-dL1-IZM*^EH3USqEv)Rd&1I z%KNbi@4c?r^z!fa<opNcPN#3()4uVm`<wNLS3b&hgGb5cev76YvqKT>JSx41XT5xJ z=h%ltWdWx}OOyh-b{&)YRrQO*xpmvV_r6;9&7XTtJS_1xIpI={rTU)T*TQdIn#tv4 zRCz3<$W(A`?&FFV2iq&p-xUAxXw&ESZ^EQ!xtTN;TP&~b^z)eCp3dXcc%jSQ?wh;b zzYp#P+j<z4Gy@tJZQME0X`#5fBlqb=;qlM5RHjeJKXWPiowGONIiab>5pUz2xg3>P z8hK85=EvRKktut5x!(~__qAt&!sDAKXg%G;Yw^_JoYJYfzWgPpzI-kDyn1&2<InNC zn4UX%+}+oC?E8b0EYFjs@ECTc8w4%;Te0%Bs0v#n56jVcLf`NF%ieOi=GW%w6VIk- zzG?|*Fuc~kX!Eh@i$qgCM}8_bosq<!92Fh8zb-Rtg0Kj;E7QtL`<$Am?EA9Xsa2>c zK(mF%L5rp7$d8S+V%{3eTf8H7rd^F=|FA!F&AUIsr*F&ONvyg3t-gFc+pp3V=^UY( zg+Je2IS^yfBYgW`;(i%#(f2&7ST=NNty+=9apl@IqryuSU7noXZVD^bu1$?z*}X$% z^6Im{_Z=vyiAdTauej`w3*UTqr&pi8o|;j7Xtl|;pB-{ChoV|OKR(Vkv(~^>R+uF+ zs_m(vnaXVLi%Mz*jnjqarsYIy&o<9jGq&lUAf~KxDRK_OW0l)h+b5kj6?($7rcdx( z(#OATH*?y0XJ0c6)Off5_jaE3nF+_%ycF@Ojfn4d<#uK(XjCbj(Dzn#TW9#gq~nv0 z>KDG+-M@5izA;y)fZ#RNx{_JK9O4r=nUn&X3sp@f$^Y4J|6tSkxMLfhrA;~Wz@_Qf zLnF4ty_2us5ISacN==PxkMs@qV-hW)Q@m3b&64pJ+jl^j|Np$heKt*&>Sq^f2yHpQ z?rkl9_Yu<st#;#1{)K|moEG{lT-@wpq8Q2`CNeE3r(+S%OoK%seH+gSYD`Vj;c^oF zdFPOVgNNsuWO;#Dvm1Msg&55#`XqC&FQIpzlX$<*{#8k*8f1mq8furaz4Ku4m;BGV z>7cdnmH4Co9AWu@MN{>$x{p`!U6!D>6DB`)Zr$2ey82pBd~~;f-L;tvi*h{T{q0S8 zw|cy9TCvBHJ<(y(5sT@pOZc7SW=u%@n{8rdR&Zh=`{y%F;wPSNDk;xDoLKQ}Wx7Su zJDnJfTK+k`Gi@r3^zFVgxy#n8s7;yYv5RGmi`8*?xw@Xqet)$K?EamMk{3>%lN=E& zyx!*i(f9B6&+pUS%abqJ=x5@!a*M=U4-*SjL9YcptqzI32i4dn@<#3|u@qMKKW5P_ z+;t-|OJHT`5#gxh(-D&exVe>{&5O4^bLaB21S8Jq-P<262{&E3LBnavlqZK}&NXte zY~3j{k!Qup>k}-RjoG+WmbT2!`yuJ+KXd=@7wVl^%uNQ)2`WPEe!en6ZW7U-jAvec z-N7Ys&!%bZQn^P>^A9a5Z4#cQFo|R7g<}=dH*bu1nY??-C*d%oM3>wtss|^DbhTKz zI!-^S887wz%`1=Q72oggeK{xj;j{Sx9@`v_7P-6%^SgfY;r%YD7xfj+Sq~Tl=Ugyp z&phmRKfXQWsCA1L<C;ZXTB~kwE_T~?;X(wvlfWt-uOIVllXW$Y?>PB5Vq1!4@N(bJ zKhOCE1V?)xpH}uNMV9ZmvVTyd8&{_>ryavBrd5x`L@x=SOZK<w%Ta4K;+(0G^!L$I z8KYFS#mD*=WEYzsKJKQ$xN(BXmFE%rt8|ac6|=0I&GL9pys_T#l5OS2YgY0FYdz$N zNWQR)zx!a+*;T38fqKtcg#A-bFY}$U+p6%IP^$426O*LJo5J-zRu-O%TvA}6X?Sa6 z<z+Fqo{U3+6VjX?J25nFRcLjNwm;>oaZr1`p7OQSG+Ep3qD6aGI=f_eaWEPhUecUo zRCi?d7s>93_7W!5%@M03zue)r`L|r%^4*cgmYL^Hs@zgq;_T^IJHyeFb7zBtR*#{I zS-+uO5$E%aHQ5IkwI;X!%Z+<jG%4co@<kex-R?I`n0I8lmul06=h9x<ow+>%jC`$A zxhBnM;5nK!@u_y$#-gu5YQA%xRV#jH-u7+pp+&v>ee!kBo3-=h+;e>EeO*F>d%vKm z!4ylsxgY$0KaE&bkshep5E>HbDr&u8+qSm0Ha98h*?~?AQ)VSUf5XSdfBcB&<cO_V zqHEVC*Tir%DNIo*Y~pfNbvvv$At*8TWV^%T1C`3n-p7}ponzX(YnGJC1Q9P6u9Cpw z3oRc_dU$sJH{bubr+mJLp=U?$!LqVsVc(s*<&%YaSf*#F^xe1rY;gR%Rg>=O@ChnX zo*fgK>>hd_xxMSxi+69H9+tQ0K6*M_@KHwmZoX{M#qPaHIkyeCj$ODPzGU+g&&3mj zvj6OPtPr9TyQzgg{!3g<=+*vO;X~D}TZ=PP+_<J(o${;u&%=lJ3t!sTOuCV=A#P&O zMAyXv=aN2f8Y}V%dL(gs{gm@;ZEz{Rt)G9;^2d?qcAdgaPBM#gC38)WNjg1be-gPo zV4-@vmxhXvs;U-8W===Vzoa<=ZH$dP2Fo1gs9bT26yegWd3%rXmQ;b=>0qr^<5@>I zl>`HVC#!R*76vAj%sgUoO7(QNzTNpHotJMeT%9-n?(A!sa*_Y)YyFobvkSe5Proj+ zKlbVY+v%<4q0IgHyQlm*^Wf);&_AgQydZswAPrSX(@m_;S$@Wxljd0R@o#m7bE7~* zp$DU{Z)r}<_P)Ty?#gr6bpGDm+hW;zByo+ag=37~<SE`FRofn3h<NSsNMeGCnaPC^ z?HBhpG|H{K!1^L$dt>hF?H8xVyWii|a_!;a$jv#-hccI3V9|0;&Xv8rtwgC+etVl} z#LF9dvXt9>XZpma^Lr)*B+l?#w&6(XVR^aQNym<*ovQt-vUJ9+Uu<5jMqaEXrQ0@V ze&sUysWYSD-#fimn*?vRS^Zk#sGe$;cf-jyx6Nl?+a}W%uZKPFo39*GV1B9IV9~Dh zNd0>J`Q!Hg>IIyX*2qt4|6)6Fp?3h&9Km@$Y!BABB^=NY>6$*jy3<|$5A*W*rEKi- zcCu3rWL`M;gCR$AgPsCozE)w^Ce5W>%MN8U2ifhh<odj&CvV~6TJEhkdAv09#WwP- zbedz(GP7gTH$#IUP5VbXh5jy{Aa+P&$?Dy64HkFsPRVULEXWdRWwk9Viv62u+?@jB zxqrRcr`IaJy?VRx$;N8a4NfB8m5kC-&ML~-y*gA|Cle|ou|f#a)eu?i*6X6hc<9pQ zyPW}IYmP3PtlxAhCZ_wSkaTn3={?&jxf{Q@9Nx)uuF0@aswKz3qG#im?_U)^x@cZZ zJ!Ej&F<33&%^THiZ8ta{1$CCbz80)8P4HU6skRuE$c;s&m(~28#Jw$8eb4%?xxZ!N z!>yKEzN$?%m5xuoHO2Eq5oe<c2eV4w5}9DXB)RwxGVXG97VFnUd0P5uh@N&i>?EY^ zkux(XedazV^S~L-Uab=+E!((Q^1eY=U3%o^TyB5;>c)+07k7S4>yF4?@*%RLvsJ-R z<7I(c!ExFD^2PpElDf=H!EOr*uKl>Q@d`(}LC~XyBhyYsbe0`EzVArtyFG99s;Ykd z_#$r4z0kpPW?zlBFPBHlWfrFgJ;yj^x}B<E5{|x~t(oGbw{(7Qtj5>i+X2oClur32 z3Hd6>q&~jt*ZIkI>JpceQESXHW(w?FBmYs{<;!<*kCvlS&7HEbcWZNQ?GT*feVpNx zSLeKv^@^p9%T)>!N|vbi^v!km<a(&wQgvE7a>F-w9;HHN?a(U@WwHCZJyYIaad^q} zFYD6(V8#8Rf1W<npT=<Q>Q%$!V?3XJ+MKuh{pNL_{pv+s<y@DS`yY=weQBxp{g<&n z<9mPovXXk0rImd0S9Mi@qQ&D6u3oK0$EIrwa=iTg*eKB@KVQGpbnD7h&rh^fb{)NO z{5Xd}#njVk4U>MD%xEZFn|vbOiEF7*2ZOdkpXvJCcMH}nn^%;x!B5fkz>RBSyLSDS z2)oU3?!t`;sV7%^XU@6M)@2lt7`ZpicKKWzaUaP7j+b|j^3B-)AXTkrwu^7>G!Kp* z4$ZH}pKP*ZGC9_oAswtE88b;Cq=}p5@7%d1PtBbKgpSS9eSPi2yyEjp6BeqQU(+sh z@?=UB3`$t@=%}l{Q0p|%VVB;L&4)c5+8*d!W0|MYsxX&%rN^50{WTv~KCk?7kbOq^ zJ<BsQEQKGkcurDiWl}acwx~lO=#hFj&x|~oAkLCkaiV^VVry8`Jsueu@obE`eEGIx zZtT2$|H{@BisW)?sv7YaM5r)nA6WW%Yp>yyM>B#J_A9(_bE{-hvFM)kV2!i7p?BE6 zBgy{v-JLH>e7adxG_xbe%stmv_NIbYG)GOqlGQwqKh2yp)l$ZKMf<r(mL_|>-)zUG z*lZNG{`zm}|2JX0G7<mSl#==6KVR=zG4tEB`t_?U3O<T^GMu;jodeq6I&0P}2K(D( zkB)S%|Gj6|E-TOyD7*R3r-sKZT)a5B{{5>uS8s3b^m&zP{r3MXw8Pd^M8{imFlA+D zYuish{nYkc&cFLT)8nc-lQw$P*8a8LtNlM)v30@P(kb%g&tw{fG&C>$)9)=6d(Pq( zv89+}_O}+sYgUU4mIP=7g~xYq?n_$PBOkeJ<FQ{gdqO%lUQ=pavQP26<7733xnFM9 zItA)Y>0G2!7_)5KLb>dv_3qOYdXxX&;^mob+FWFLFv8KlT;GX>W9f}OOS`vi`)Fam zx=F>eCNj!1E@so5Z5xv<Gybp$%@%N#Z0QjQ<k0${HFE;XOo6qgP8==59_lx*-E{Xa zG(5#wmE?Z!(8l0po6oA`ynMSLLhnalq1cou87yztZ#Ay}S7Z0Bb3e0Uz@@}3%*la= z5?en!{_w$2+wO5dgXfN)$Kn;7cRZTE-z8^_y2H8Y8+wHo{Qc#2Bw{w3i?=_MuEM2_ zxj~$BjQ?>z^;K<5x^W_{Xr|24OW7`o6RcLqO2q4hU)tTtd(S4gvq`YY!E?$47DorA zKgCKfL&G#hg4%Q<cXjpc<J<P-tCH)Bv#N)d>}+9FWc1=Ra&$2}bK%Af553vS(^sp` zKRfY!+DVsrchm}dIGDrsmf64FJ#W>W_4EF}_4(YURJDFN+b{O=FlK3^wKC@4gn$1N zU)#mZRbR+rF!|(%$MXMYw6(GA`*}8hQ^m)mv@<g{9)I2=ZQl33=DBsvhi3UTUve#; zSA4msx7X4cwidvB=a);~k$WmW-ro57w+!geg!n&?#CLwbS8e%xPVv2K*Xv#`oj${^ z_Sb^rw{G9A{PD2;=e_UyjyJJ#-@EqLa)M&Z4gJ4Pp>J&6wwegCPTIuyQYEPB`D$aa z<lgy#uVwr+r})lYbS!VasCMmw!i^zn^Up3wd9nG?q$9f<x4NuqxN&5jhsV){mzOIF zWF$}2Vqt9k$8^)-;=SOMQ%g>Iywu$mrp2^!hEb}}>hSfcUuH~9=~0+`cGB9F%)*;f zP8L0zSHpDch(-DYC8tv}QdeJpD0I3<GuW}oOC-?Dd1DAu;>i}lb3gCxW@r^;TFY}P zB1Gu|*P|l~dXmrnI=f{H&+^*OVm+Hy>~K+0@v3Y}ZOEN__fE~>-kML7r$1V=q=$L( z0~e<?tc+rsqKz9Oo)$PM$*zgt)^fY9j{W)EYO~GvOHERP-4q4FmekHrn9!lXFkNA8 z|K)>6In?(UX}i2C@e7FhsbjxiG>O-V>le3ekEChW^|;AA+3!;STDh*_4e}_7oP734 zV9SD-S5LmG#z<>9sc0?cNImww@D)>{K%iFil1UzkmQR=Llu*`)_Ga^7>h@T_xIn7g zCEGV}`h?Vz(+-8*m+w5^eZ}qa_O<OQngP;JZ(P{h*>>`~VS<*N%*9QyyewtTU+(RY zsyMZzUM=8e?Z4`<qm8ZmEto2PJZv{kJ0l@i`z3JSpQrl!-~IYoGY@ph?M&lz(AI!= zyI$)pnX>0~?E6PO#^)X^mj9~(x(WMUo9+GYpvl6@uUErCX@T9g?$yfWpFq23ve)fw zTfJ^q*8V-;wq))r`S5xEf0<;S($Z3y@;ikw6%SkI)c^bW=j{DIyybTakJnY^HW(%! z`|#s&KPYGF?b&eaNX*f96MLD80;d^pX^JNIY<3A`yK&EhUtvl(1GA>Bs({kl{!ix; zG-aP!DEc|g(G3Wm?XJ}t#Q5MWn^&8KjPR{vLDA98r3<DU;%pU|W}&H+(%_l2NJC|# zE0gqtH4YP{bk-=Jy1MvOs#~9wV|={eYHkyA^XgQd{FnlcYk8Huy|cF$eVSvbGQ~qk z;MT-$rER6T%F?L<K}}od9bufQ!F(<;_M|YYrr<gEt6#pB1Yb9r<Juj6Osg@h>80?p z3s+2L?OSqY*}SrMJ73G4t2@7Q2FC@%oeIu#*pk!>&unwzH~lG<Vt3?Li-+r--?OVD zx92g(@A<@asHW}6)Co*$CfNPnbtpn7NHYGPDO0ch`6OM7iIcKBLltjD$Z#b)TD^X5 z)IQ<7+Z8jj4MjJNLd=?3eU{4if7$i>f5uu)C(k8L4h^4@KN;QRS(Ng^NJ{Xh<@rXQ z7n)x$Zd`kJ`kY>dl@pbkO*t?9tke%vshhWPvqh?>kn;+oiu^#Q1uEBC_iU=s-8!>H zFgQ#(r8Cy!-htYmRaptYmhA2AnQ8V%=a{M7ceT37t9}$8j+bG~$<AiJ@p{tppU>x? zKQq&~@=>Sy4CC~33)t?=G)@l+|NeY-P2KOe+lzm{-Twa5j}H$IOInxZJdJtl587d~ zeoEcaDSw{V|5Km;>&o&U@BjbHm#cWdSXEsepU$1n_p@dmr?A?Ed-wLmZ;L+~&$dKh zi^=umsSd5CD=dyhdaiIvnJ|m<5~sA2SIDi+s&kL>nY`hi=yvUAP(h5IVCp6b;{|6b znk)n|gW`ja-`LhUWy{x(Du)ycIJo!L{#8l!t*uqwXlSuKAhBVC*vd^2=`*crxw_+O zT9x^&r)*5(d2N=TdU%$oO!=G6E7w>!{&4KNw=Ztmo=r`c&s*FLpU9fR)E>-uGiTmX z?J%R%KM_kxJVX=Ms`a$+JD3Tniri9_VAm_mSp6d7{euh5YJo;}+s{jQFWlcfD`4T; zr$3L+e>UT0yJ6uWmM$x|WzTx{Epc$GGHzzhnUi2VYistk55L*#j{oQsuDt*Ie)Hsi z@7J5MWgk>YO%V|6U}!&L*}FBNSItFHRbrx0f#RM@XOET=7mg%m#|0D433?cqshvvm zC^_^ZP<Kttb~#O^ExrMb2aYklHQ|f53Tr%&(Ofo5f#bvqo<m$~u6ZovXjKa8ipW0U zHic{2)YE30^UiWb9rHUPv`DC1P)z$z;Yo)FYmQ7z=v62Y%9IIX^GJGhL?|^YV@>u_ z>$*vt%GZ9)HnlD9nClVuYyR6Tg*W$9Ha$Nv!{@?*PT~C<*4Lk1W#RBKJ@vh$d7e!0 zGM}4|*Bou!x4CHNp77f?e?A;${Biev-S+O^Sr-?%f^L4^U7Ke&f4zk7H@2@|zk&`6 zOg!B7c9Rds#^Z0VT)Fb*Q-nmDOJGRlzaB~B83u`m^v+i+KRudb<}J~-J65hu@#dS^ z+Po3jJO6w-ttr;sBVpK-+-JFLlaH5W#_q}L{%N<iWIDgAE-p4UPCHX^`S(WStgNgV zmc`HFzCZBPoN1OT#V%WNLGJuofu@s_)r}JmwV1~~>Rr^)%x^ctna{FC;YauHJ>UA0 ze|$(QGOf(|RLQm1mM1&s<E4%bb!F=}?%1LkZ!!Oodh3T(Gvk{I_I*F|oil2Y#)619 z$0NP<CcE?5xN{uRc(ma#-_msp8x>}|rW&<4x`?p41Ui_34(vX#p)GBZf&$myJF%h~ zIts0a)KcBH@GM@xe}0bM=~q`*8y=h3yI_vU#X_I@din469~ji<RtWtxP?~;nLiZ;Z zBNYx2US8!FZ(l9jxbUQ~*7FG-J>UA$r>_bLa&0)zaOcuZ*Vx##<(|<Kf+lnu<<#YB zuh)q@nE$?>BlgAPJ;C>Ui(`$Cam?8!k?t|6C241eUy{5=uI%^!&+OzXKYX84{w`9c z@J-+k6$!^R!lyiaHijs9c5!4E`YH7ujB4~VIrd{huBJ+mh741-?75#o8z-HbKCMt< z?vK)ob~mKlMV`HQQ`2iONg?#;%eU?4DyLqJYTU|}o%{5(M6<($7ZNHa*UT>5x!~Zd z=f6Vbrw?DuwBFZd3LS;ll6)Q|7tJ|rG5y{C_u8xv&+jaim_0$Fw_uXO;~7SkJnZs6 zZ!Hix*!Vm5`26w~iGV*^RS)=H@37S=|CfEP<@{vs+279Uhl{e?@KrF~xN_wPXixgK z+}jbG(|Au$(_OrO|9tEBdnQj*b`QH|{is8^;9TL~uh*GDYskW8bw58ld;9IT{2DIm z^J_lE?e~-~JR)fG`Hb<GFJD0WN2{u;A~qy2ZcaZhSM=Ai_}Pa;-1?wnoes5f-`rKI z4Z6E?vYPLzHN|hYUcYqzzJ1F2d&lj*8UFh9>&G$keTFYSKA&GdPt|)GX!XUj^YhOy za_t6<DZQ`0|C?dQk4N1vU%!4l`~Dv_hIY9sjcZYPd%uPqSY6Eg{Kd8Cd{rK2D{JeQ z@7~Fk<grgU{~ToD+qZA?XZ5Ifg4X8oIAmvMKm7>0f%4zKI=6ngv+L`=YERRTKlkWp z_s>(|`<N;&l|G#szNzeOl$Dhg=qB2~fB%9m8gK4Mk!bt!{rl#en??+vU9YDM-@V!N z7j!A?qods~U%q^}bb8#P-MeRBT^(M0kX4*#=lic;zs6L*-TLL*H&9D+nqKUwW4+Qp zcklnb+wt|*ZQF{j$Ch8bd-v?8r>8;NmG|!5d#B(qZ?&(H@k}1j1%4oZP7RNH_;h-F z+Usj;L3=K%zy8sRlmA&W?bk1>C8r);3Q8_77w6^mU6Ipvr0S_Zr>lmj7RLlHr6mrh z7?##7-Zy1ZfELrsdN&8V*-O{&Z{Tv8aA^9!HL0JLG_P2{UiDgPPpO3ZMkR-64QuzE zYhJ#4y?o`)&Lc-GG%uV>=vf%?YI#VX;jzH*>nA>Ui%pDZcQyVz!C7M}_moL9{_U7u zEmzeb{A`YobFy;ck`rl0PqJRE%$ISit!4K8%FB}IQ5<aiGp5hSZDOa9hhWo(<ST0? zoH($0Vd8{^n^!kKJS;uI%t7Ut`)QFb71y)N`uxJy#T@o@mur3ZYS}>xHIp7C@svV` zJMqU}Dc#C2TX*9G@AW@ZZq0H#_w&Hc36oW<)cj7VSS{PWfBrou`P8+YThIHOtn1m# znZX>kIOXQ?j~r7c?JDV*yFFZa?T06KBU=PAau2v#sCR7YGML1Zo%!`?`SS@kN<!ji z-B)LEYHRRy|F&{VxcHi>8O)uXFJHV_vN&0L?%cN?*%u3YOsCyjXSYV=!IJmIQ(m^S zSU+I+7H?)4@!Y`AIq9J0mW?-54yMRCx7zJZ3SabG%QR-==TBT0y(8}ioM!*G`S7QW zyvGgpKD|@>?RV(W#(w6gpp5M7$DQi)65ia{_~)g6{iBEN@@lis7CoDp{^{QLebXQJ z+s}*Koc8fn_WF&5kKI6rGZ~e>3h}de$O2kX9qe!0THN>a^z`@NOyz1mIPUw{n-AK@ z3d*0wKc7y2Z)o)FjPdy=?{>dm7NJvgH8gx<&CjB=^YhN8+kKXtSM^G>&-$H3T*brI zQ@@_itJW*OTPl7`0@OF2rW<|i%uHj@`9D7&^4Fh;OrOgd5csJrXe-;ar$sws<<_rU z`EcFtcS+aQMBXXA9t%36OvRJUHvhrz1D3OFDvdz*9D7gKTdOgr-{upC=cI!Ff4_g; z_kC|aXfr%$$69mTd(cMwg$o<4-|xBHA67LvBQujx!sWyw4JWUYTd&8R-c$Lx;=@69 z&ZdT>jU56_>~a+im;J1JL3gRY|NrkjXix7UPW6Iok?9|QJnk>PSNXi~e(m>(Dx9Eo zwrkg}1+|_*iq6}9XSl~}*8u9%#S|VDEh#JeG<p7?mZ{p|M%CYP>^?N|gU+$|*#G}W zf6a62`zzPXKbbPazTOUWkj=p+);s0*YeDN~|NVSk{P*ki&o37Dhi&`#`~LrV&z_}$ znqvQc9Jjx8=gt|+=W`Cb+kFxQMNiuKdA<t+ZalW!_3PE@pKsFbPtPsCcM`Pk^VO?Y z7Vr0bw)p?&Gw4{GdtY|0Kjh5ec)H`E$I3lSQ@XSYCk5QUaOT8BWzFNRyLMY?ih8kV z7&We0VdliqBg~<FxkJ!>!2t`_bH~>|*`)YX<)h=7YZKO=EWYr>lVjmY)@#pMx!g5G zk7cdd`od-M`jeBrt1r))GPP%Sfa(edK{iPy^%+$cRIIGGU%Y<VUvIjzS7YI%<@2hh zIrGnSOiq?t?L9?CV=-q>szQYeTU(8<i?3euM!jA&!+Wf`DrRrBFH5cIb=0_Z+uHKQ zhr@-AE=k@R>|xG|nxDQ*=C=5E<Z<NwQtoK0?MX|Ptlio>^YOAxJ9kg^wf%2joiC?) zJaqow`gcL0dwtID%ZPV-ePWW%d$Ucc%xVn>*Yrj5<SY0cP+w#Clkr>s(Q}MVjVw%d ziiJ)>$<wAc9G?CC&m0N$iH1jhE1jOC8~rI`y4&qH#(P7q?*0D#_*%J4l}g6nyk`0K z&v};p4hs)24_`g6Zr}aqKlzem?v(zna&tSj^O5cQWjF2|I{2~K#8kAvj7`_@THx9+ z&)BINLLpjg(tXOM4yx;dPGl;5y5XX*#nq~{;FkTqe~MQ5Mju%dn+wENZkhkA$wBGm zt2Zgn`(k%o5mtR()9Unk@!q077W@0>W;?`8W7W)Ux~8b{G&El2+!6(m!by{s2v1SB zHgsE9s4>-9c(RIN(9cbUuNW3O{-}2s<x<yOIhiBd@RfktE_3T`Rb>g^KD~Or!CqsI z#VzTIH@`lrO-z5y8)Ecmk?a5W-JkAeJ$TwY-Gp(^yIrqm7^m}rE*KAwExj7j`K@^V zZyEc4ANwmm&%S>q-Trr^-KUBD1rH7|*8TrpKmYsw|9{uS?w<Db_4Uv0^<Ui2|C9k8 zoiYF4m*t>J?$Gah-|g=GIA;E-H@~JizxH)>Pj9d9?J&)w*Z2P`Z4rnmILMlFYYXQG zxAy9HJKO93J+FV}9sf%xzv8fT!(y$zDU;0i|2!M)!m>xI{NK;#`yYH?v3hlP(#8|J zN?(Ikxz8)Teej^;x;>w~^!EQL0xi$2`}cYN=Y#xy+kf4!`FwWI*R}aiyR_F?G%{Q} zD{}w$z3+8zAMbs$>GTZqe7VDi4}&gqS6>rfbW(NC@4N4xwcG!BxaIlYACJ0kZb)Qa zUv+i0grwxmsNaw6|0Vx>r2nsJeeK(9(B<zE$v<AW+n;)Lw7c^5?R&@iWUc)I&i?xK zYsarwt1XM3aAaR!H`mQ&|L3{y3y#Z{f4F(RZW`!ZizgQrIx~R!UFknRJ-t(QJ9p1h z-TawK2d>8y^MVdh2uZoXYktR}y4o6gQ~lj5b@u;%o(FZ_HkZAPvio(h|I<_b`k#^a zmus)v(e&|Sq2B&KpH@Eq^?U#S>O~q=a_@_n&$oWN_H516BZ(U|p5B(5v(?APFJNYl z+WjfZx2~OCls74A=bPhAsWS`CakhNXx*YP<;l>*GfP{||HSCy<X?yME78hcZ5?&tn zu~2LwYi5*cr=n<6RMv}^?;IoAFEIvji3qJ`QPO$T@<BC%S=U!puHr>tRoa=PnxZC+ z`{&x)%`e=woXooUSw%3TLssFfNwc`Tw3-eGubs9`Y)R2P9nRKE6C~Ux{di~a&?HDB z%X4ODRuhBOt=$Ia1Qr@(Hf`?Wl{VX0bu}yMQ{@_OPaXx4m8MT(PraF@CU?)^+}i)Y z>kH4_GJY9n-oMI2b4QE9nTZn3MGu17P1#z$J-$7s{9079Vdvsm%Q|i-9y*{MbM5%< zh-|?_({p3R+?zk_?K#9bKTu<i|4dKWMvl(OflO;PpK)ib?C4cBZA()8bW#7(dG>YF ze_p=QAaJD6XerC9H@jDCSr)W9A*k8VaARZVCyStnImIqslcesSmh@`fvhT{fp07JQ zW-`54Qg5fMtM=dc72_o(Z6EpDtIhAS6m2oTkpEwMmJ7=q)9=h%p8P-my~X^)r9<A^ zSnk}rckcb)d+!7Fri1PoU-tF6s^_8ScHb=-Kx@hOKj7#ECA65TmrFqx&V%ZdR{fer zS?jV7?e#y}FK^rZ<573yz8cHz_o`lt{9OHbx&2>Fc7C}hrt2%uPMQ7g5V!u4?c1mS zez!Yc>L;`O<WFz&>wmM#mdk=}vY$8kk8S*)*ZcozyZ6aFT(kLH(#c7x!Qaiz&5KW} zPB*ZzIg`8n?zcVPx98op0_|o3WvqXn^#2!i-H0u{8mb<8@ZYQT|FWchGJ_I3qyM5l z)p`cdnH-W55(!7UMCTNrvpoNLhTXS~{R^i&IwqZOvruPG-QTKzfA9aFyKI@-y^nq6 zK6mS%P7U{yJ-qQ%y3FyI^1G!yeSMd%Uq7B5|2v9L#^S*AeP5Pl{<hsF5`X{t=7SQ> z8zWNg?Ww%{u72O%wY)aQiwsW4?6CWB#!7yFqLF%Lc)0oGsYb^nri5+Tw&l{LTaP?h z6O5T2ta0XgtH1J)Z)|C=_eM2U-{h>qsZlbQuU__*X!8j>b)<8@zF&5NZsw!}Lk$ND z$LwhBK#2v+y+M51I#wJfo_}&l^jIL;81|&gl~2aXL61v9N;38Jw%jX^q`Jk=yR#nB zu040T-NZM*>(|Zg7JM=`9a|?HG1a<i<S7)qGR$L=gsNyzmOsy2=hqE~+u2{fdiCj} zQINt`B@Sh|`@cliE*1Lx{JfK<<<<8ZbDw-z$XHkRe{anz<LjG#HoEV4xa)Pq)->MC ztd5prQm#9r+${2cthkbOuOx|Q>yZf(-lm=_jvA_Ub_%x}p4;EPRm$_x;dO%Nru+WA zAXX4Jwe-fy^CH}ZlbSYgNKV#j59o4QIN_}2x6P%m@9V4n{gd#awmK+#3tz_~nVm6x z8eJV*+_cvJNYV|8Skj>4dvo94%q1HlXId#QJExdiw&sVNSGuCF>@|xiAKuTu+}|K& zvF`hM>DE`Fw;!M0r~aDPCNlCzL{>z6{(1exvv2-?WZECfyGQ2ZB-Mt~({!CRk1q3_ zEg>akmH2n#ak=D@k|{|WE!IwdbNy)U_PfV4m(Mw5egCK5ww#+z)z#MKcS|mth%R5h zp8tc}<kjnTy=vL7;>ppJ@Tx*gKaS@>?f1Lohd%F}vE%Et==d$Qs-A~Hr$ruE9Z(7? zMisl1K-*3Jd#OD6c02$1IqUaNK%1FBJDqNBPUp|BzJ2@0^7>!PC+F2~y1pstC>O)K zJ)h4BU+XcvQ~UicgHG(OFO{;vwe_I#)_>Q(?)X1U30(}@OF=zM&q*InDEHeuu6tcM z`TLz>{z4i1$93X55g*pLNjJQ&`@Y*lv+_YB`;RB;_MYkK&o}R1!8T8v<-)Cy6CswJ z7r53qa21#xvvQPh-Lh@FQAG;Jri=*+rvkIGm34k(O#dZ%Ek(Tk;Ro?bO#v_8mEBR? zv!cDGcnK~|;^yd{vVf_zxNgr3F~Ny^e=2sWEZiEQ;+O2R)oE6U!8SMDl}3?s7lh4L zS$8xfOLUvvUH|-i{hcuf7CN`zxVV4v=X18~vKn(rJX9}63AQmd@(G?;Ge4m4!vn=* z$J`9RJ``?Ha5!neomzGx$I<%igAW?Uw{EYzrnW*gbxva~d%uB&#i3LCmLA#K6>hrK zDI&mWQ~Gzof6x2>%}lLb{bR3o-SlM|OY)D!OgsD1^?7%M=1EpY%e4nNr+nj!)2xx7 zS2`i8xzui&rJ>=|9X_V(3@xl4^_pdNZAe*o>E6~{!3Z5c4IyohT(3D-Rvbyq@|@YV z^3vU_o<X|G6IufK0xYr}xpJ0?Sv@~~VrNgOr{+b+20rFRd(@i_X$1v;ReX3%c<0T# z#T7?cpErK2Z9cVfampF4|IG)j9+{k6l+~hthP$=&@r@VL&pUnTQ*1iE_TZO$2PUtV zzb~z^BjaTH#7C;JJUI{k3&d?=DY&@Em4Szc$L6uw@9*!~D*`zbDvUlZmjByvb#?gX zv-x$x4d-i~83z|?mO6buX1;GC=&&&LKWAqew|91SuFROc>*V7Djm-L|KK?C#_-uAQ z+k?CB>%L#9-JkdKJLoiP`TswTgEsYmMixMaqAs`p`|@*LjlVzt(WHqdPkO4Usrl{l z{VOxmIQ`t`ThEK<Mt}XhYTtg#;%5RZ|CFlt1pkS+V*ft<*83+<RFadEGuF;DOg^?* z?lGvBwQm2vs-m4T=64F1tG~Z{y8i#K_0pG};uO4mEmO?8eA9}Pn-y5nJ%b;6FKj%* z>AiBNi%sNNIZcj3HfM9+igdB+h-LFKJ?=hnj-hVO^jSesGEtgg-`6JHY&v>HP3^?f z;*dE<B0Db$I<=oLaLPEE5~Iw+RP>V}JNW+m4A!XD4B16Yt=B9M8My0(CtObUFSvE; z>X&bNDc=v+-K#k{`{Z*aC0U^rOkP@3d@f|Pd=b`v#mVLD>^$Z4<SSWmk|KvvkMlFl z{JJ|bD1GIumV*Z!qoS=h9P3Y!ma#e1)+=q1dsg#GmZor_&)T5WqNGU&Ckob;J+J?C zW!u_4->$At`nE=I-o0-u(sGpz3;#0DG2GwJI+xpHb?Bszo|C-Z7z@okI8$PdBA1Dm zrW5NzzKKREmnMWas=Ipmojt)SzrLx^BKyFx2%XN4$L)<Q{Zu<wPSNg}dR$V|-)KX= zz3kk%SF%jETnqka;^k#8sBGM4`TT;@&jp!}We=7nz3@J-w7a*S*K6{U)U<PRSYMo( zqBKG8cj1Jo%VM)OtYlR=Rw2H@pv~lmc}vG~%kutNW_^z;S2mtc6k<GnYUcX|%eTC0 ztz9Wqar2R?_wUzB_f0-J|H{Q%x3~`MtNk5!<+<PGDgCu?lK1?5o1gye%}r2!`sU{5 zbg#}ohs5_8gr2jO^L*qjaX>^cCo{A1-ub^dg698YE1pbrzp<y%SUY^(lQ)~sFWbL= zez*R<8L_*|K7x*t+<$2wXzQD}2~%E94$t$LYfs+&zi2DB|5c@dmDQ;=k(=jzykk{Y zfBt*%n%V91GWUP|SaEE|^FM(JJr8%iUiVn~{tq_LsMwDq>UIa&?SD9enz}C*b<dmH zVOCJ|#K~8$$7t#C)ou!V7qPcEdN64$-KeK{#+8ScPe}BWdoLqjQ_Q?QTaQeYGBdT9 z{%f9tyW0|mm&>ESoSWZW%%)wWqV({>Lq)4-@5nhF{ZlupscyY?e3yt){I{(WJmili zO=elDW5Imr(VFC(H9o~FU3Axe*gXI4!LC$ok14KdoGbY}<|-B#Zsb|^O?~q}mz6Bd zhn=T%`7RNg!}?gouS(eEuB&!S!w~}`J5TRo&iR#V3)swTH%?9Mo-Ww7b7hUQXv>>h zJ7@p9YaMA&F84Y8ysKuwH6iZyPTs33YCJ66yVC<D^*0xuPQKE{UU+JDwAh*06AL?y z4)qDWU<$Lk^{LWFyXShF$6^_?QU#ST_kH#ODoc(j%yI7E$X3<s4OBXMi>1@a(tuB- z$)fPg+{<U*{j+sxm9gRp5b9w~mbIF4?}4(+IWL}jA?gBl6QZ9OoV>WtNnPbw)l<V# zP0vRa55)O5W*iMFuw>!v6Up4%vQS4@=;8gEiK#xvlDJ!LZ{B=0b#IOPTzU0b4x3)2 zsV}QyUcSD#$@9sLded1=dFST+e<=R%Xx4+&?&&&=cQz)oGn}5TZ~wBj{#cLXmoHxe zR))ltFhv}HcX#(p+v;y2mh0v8_9h%;T6Oi+W?PXN|D@(|A3l7TLH#U;&Aq?BlOEn& z6qC2_XBueZWYJO4@C}up)0z|>{J#JHU%mCm6(L$O76lEUIm?`zM%!|379BGC`eSa@ zm(v?9Zf4)vSNl6;+r2hkX}^g0&1q-1{N?54HMFzyTN#q{?aj^e75lE*zfYI4-BI+^ zYsr)^-@p4?Zk^AqtgKw~So%Krte4BneAh&82MtNh|5BUrV5Va0f~69PE4Y=<tyVaf z%KOQVU4O!@cJcJ16N6SBxp2WiH&-=ZjiE%~;uWF5tCM|t`Wiph#u*i}M?Vbkm^Ir= zC-P3Wb74vbhk;K|xJHZO+O?{ac09Uj#xgNzf|Qljt<FUp$)Z6KOe+O~6j_$|DPH7Q z_~U8w_kwSk&p*sBzjsno+i&UO#V-Hf-JP?kfU&ceb4uHlMHf7tFIDP(@4T5~N=HU! zo~mb-h4@cTv2%&JOhJz~RUXwid9b<t#fuDgt^5Ale|D;8W@j&4y<1jQCrsj)x>`k% zdf&m9u(bf*_F@Mmm(TZG8Q@ZF&US6Lw81q)BeQeQ)XfA~Sf`zx;hB3j`$zlyJ5ITe z6ppSqv1S|Vn>&>=oPW<#5K+_;H(I@X@=aq^f1AG&O;UmDTok7#zx>n6!#hoKb#HJ_ z(Uz?u8K=q>J~gSVGzgrTlC!8swb6<D+O&z+5_}J=JAAv)FCp91N%qJ8e4cYsTXYlx z8jeh?GWIpoT)M8ONr6Kr(9T~(BWsC8xU%WW^1D*q9>QyQjBmFdkZkw25?SG(*yG|I z5a^PXrE*dB%JN;l>XnZ&5{zZck8gjMG;h^o`_-OLA|_S*dz8)j)tFm{_s_S-=KAKg z%-izrp8EFo_Dt*Ycb>&JLC1C~E`1{Z@1cC0facCut5*B1dh_M$SKn0bYrJCne;n2C zcsyhK{=aX}%rbp#`5n|gOzwGj$y<M}mi+aLSFRj+Iz8U5bhn?D-mVvmGH=hV|MxSv zZMryjY3bH`mn)2F{{OyzT;j0xy^nnNKF|BkpnvA?Z>NIaZ?`kMpH(>ih&R82d3E^u zwA0gcFFWmiy}t0}rKRdCR{j5$|DWvuXry3e#~dp$y_gfA7Oa}O`tq-u_e!tFp0D7^ zuev<@#hW)z{{4QRUQsb)^Es>6EbZF`nzGmJWJ}Om{b{DcQk%vd*EaJv3is`7eD3C6 zE$sDEdwIzr_gsnjAJtYK-|f+)F#YM)pF-=WFv)6Mih6W>U#eu`Im<;cE-SZAT@c`q z-8#ug`tPy}QJd1f7A=bL5a5tuljZ38skAk#ccY<ve#>TyM8Tj*YSW%ATXv@6p)XUM z;+MUthkn&<oVbzm(X560>$Pp?8b@wPFq6$aD`QnLV{Y}g2R#R(ymd{ltP)){RmxK) zc@mfB)?*JY2+WmrEebqw<cG>Ri5|}tDyco52A(~aq*PU%G}_wRU%bn4T{YqE?{9+Y zhTP(3)GkRaG-dwH_u<F0<1>w`&7RMzRm*KvS}2l{%TeMG@_(|Rn&2CIlN0Nhtqqr* zn#Iap@jLtep+&6P8dGj@PEj&pn#^&@Wg(}-^T19ux$Qjidd4LMb54Gok#+S^Ooy+k zJDZzEf9Q$V9n)euuQ{1de%zO0van{!nFj|2%WQV`SHG*B(aV3&-!F1j)SqlFqwtNz zX0JCIYq0u7)T~*c?srVW|HI}>>qQhF3qL+`Rg29%E4W}%RM<xYwU5a!b?UNw#C9ru zn4hcA?8E0%c(JNw&KLF9A)VX!%$I)iUHkdY-p2E3LNDJ|m~va`RT=J!;@#5&>gRY) z@@ZwbUvyd*biO2LX~mv*rRyJC-~Y)6YWqn_Nj>`YdVRg)`OnYm|2=<mV`H;){+@~7 z_kG{H=OJ(Y1JL=H>vq3W>QVxgs(w>nm%X`haQnWmx}Sd9e7{>R4>~9?a&sE5cG#K+ zlf3n2zG7Vinl%FnXRO`%dfo0H2iWZn92Jj01KPR&?Ck8HN7VcJ?tn(tJ!UQY^X~mW zJ<##fm2b1-PlxaOB$~JX?>EiT4@VDy2Kcv5Gd^e0{CeH)zUzCQnSu_0zr0OSLgGQ6 z^}7Yjm$#R`z6LtJ^3So5<>%}FeGXY2`tJe%zXtg~57_s-^vzFtduuCb-s#U1b^C)+ zr|17UIp1gMy@SHboZI;VHAHs2TsFJn>+1Nk>~<d*89*cd+w$+9+xdLnY0y~Mhjrz9 z!AJG-*L`TdQ~iGLlOoG~UzY0oYG1x~e)H<}`(}ZH>H7YEU-vwgeg6QoqaJh?Gw3#u zl9DO*zc<@6+hqQIqHcfk*4FHuUoLs?{CX`KH1B+KXR$iyMBMpbzs@VaSDABrTW^2O z6J^kS-S_UrfkrPstP0=TWn2BtNAMuqJo!&QJDl{|k64?PzBt^+dTn>u((qE5X$Geh zU5{Lu6TdJ+%hb@!^5yZp3pd>}=$;_()Opsd*@1}-2NPnuHcw;yoF1$r=9%n1C#-XI zDx15TVcw*exZ;Wr0-ldNgq&v`i&!x2h~4S)%VtFJrU&(GUZS>8?D~O<q+chJr3=p) zTA4jlKk~rC*J;+Z8(Yg8oc2iuwNF}DF5b=1>a?0+Ww4ujTckxjqwi5AwXF_aE=qG9 zyd4EJ?02%f_gd%Eck%AELnltK{QfTY=*!jB7XpvmIKtAObK^*`|NDfmvrNy-wr1~j z<>)TtG}T@)OKWRX>kWxZOWY=fteCob%5n9ZJF~6X`SPCM37+=hocX@F&-(OO{@Dh) zDVezJOxqG-q1qYSQ^Yti<jEnX));ONN5lIq9L`L!4qmRs#p-W$-@5E_aC9%(UJ`J| zG`L&&Tb_K{|8I<D`8T~{G?NQk5>1wFuw?Aqc=PAO?l0G>lr#coY98(HWOmeGURBs5 z7WeXsmC{PbH#&tf$^jA+S?$wpyRI$eVD2<kP!O#)_?6hF`GcwS@G-;f{jv3OdmI0K zD|~%U@RU-vc>OQeA8Do^ijI44W8wMGEdQrLqwB{r^Zh5E+kM}e>2>37`Tet^;W36& zFMoUeNO=Aa7SIB^pBLKgj<nl-S-A4I_EauVe+hK{>ayJWw_C3V=}rInWx4%X&@mU8 z*;}J}?f+i3pIdgn-TqJFk|}$>?|uI?|KGFxW$)~3etg(scj)f!a{sd@{$5#bcXYYk zSIq;*=luDy+}?I2^SA3q*TwGs0lK6FG|g=H|L1w;51`4Q`G20MU*5L+=d;<%m#qMu zq@jQ7^Z!*hHmCEyzP9%9@B9Dl-dA1UU2%Q)J=3jb1_lSJ?|qiLwm#net>HOK&}oRE ztOFY324PSZ0v-D@NhPM_qASQSP>BN?M-T4To_@OK0kixA(AhJ~-@aeiF865DX}!nq z|Gj&^Y_9e>%e;L*pREk~bba49(>cYUn_8Z<N$1Vj)_*&1cklPT?`zNB6yBM8+ib~{ zV7Db!Wp8gC1=XLuFU&r?nc#Hc-o3WXE9JK^aIAFjYSM602y{wVdPK@m;%VWb|9WLt zZu_yEJ*%pwuBI`?%c5uhF|PMdT)nt_Rkge(hOH7QwiG)zw^#Y-4wg)lw`X11*xfy| z+ZJ%%y6q)nQ#9k|=I0Zx91}QKknzHxTTI{OG(*cl^CzAyz6R$W^(;)|vHt#Uk!nWT z+t%ko8t#*%=6reeaLv2CZQt^fkFC-3;61j?Vj_c73(ISZnjZ$<&%Yb#sB4C2-w06% z>6&0S|C~9`wGG!cmOl{C&CTWE@BeV)*l~-`UreV&&Az!SSK7MlUCPNru5*fiWlnjl z)yepjhoe2DQGdO4yMU0YNm%5R;u|`ynGX&yG+*R6tGo70Ms`x_d!a`~l7e16B_0bq zni!TU_XsZ0bM$QNE7H&vxYQtGV!riaRL<h1D;tC-UHNg{ByMKH@po^ZFhyM2-4j%- zeOgQ>@yiLuXXj_R&v^gn!93X=CdU#yeR*!W2rN}OCs)eM{m@szGs`2iX;RmYFlNc5 zpysek=D}K>8z(HA#^E}dXQJEVAn!>kJ^lQ_z1b?~7BKq;>#4l>vpxCLw$e%ETi#Tg zZ1^d8ZT?#G3BuRUNB$_}O1$3vnKk=CYVYIQtZ|b-XGL8J_D}u!=_wB{@5dL5`#0s@ z-Zoi^>DH}V5!>@*`)$A72=TvGtT_Gj#<I6jV)}7D0xY0vi(S6vL*&U+e}8^Zv*_lg z)FXvH_4W4rHXja5NqkVD6TfecY4)`XmoFa%E%4Z1_t*0`hqz9}0n6ueobBeP|NZs# z&Aq*|ofd*Ct7E;=H@9YAzp@Q9H@tT3TF|VDdab^dwRPm~GF@r&yg6p9i~ByGx1Yan zpWUjfTHEi}S-11c&)XKKAtE6oqr$=T?99y1+B;|J?|8tp<=Xk#JJv;PY;x@u+gSIv zN=;qef0wV`^yIIvu73IYb>Y^u$H#he?(O**`P(pjUChau>GLd0b-vp9eOP*Js&@FL z>(|}g-PvcG<t9Bo)~n9aAm6=hn;Gal=CCyp2XEYvD8E<ve9QSIeZPKgEO{Bk#>NJ^ zVdLh$+TWhvIM&yFU2S;Gr+ewesN#P=pZmLB1FhYt`}^zpUF#bS?&;~)N0S(XwS(76 zZV`GBbMN^JSIZ^^cL9zbPmi9IXK$98Y@fcNj7igF+T&;5`-B%Ki*)(EIN*P3!liz> zV!yQ72+haJi{})cDvFvlyRhQ;3Ine8rE{_#-BMY5lw%=FVV0zvbo#$JGiBst9zAq7 zFFsiL{MQMwK>p=oOEP)RCG|eMsO!Hm{XXM4`^P+8y1p!4Rn5$r?EL(}YeQD38m<mo zztF~}>2jY3E60-l48@1_|KIrC`(nNR@rfH8&F*ax7p>*hW&D2qu~S^qA6WR|$mHnG z$1^5Qbo@0<cj3y2M~&`g7jE7>dC7He#@d30X<b)1w|E<L=!6@7-6xtjLF>o_p)Q7O z)oY=ghZ}14ojCI@Z&8w*;%rI%@STqzvP)Xr@Xum78#r;rl*Ptx9vxiEKOrRR3Ag2} z=vgmc$DZj5_FEj(xzficK<mi~SH-otx;%X0JAXf{UfJs}km2het<B!ob7}uu!<ekd zJsEaN8L1iP<M?>x9)A3{JVW>Ci+Ar1E?hY!S?g)ws;wgJjN$q$>AB27Ok9e!F1=GG zJqr>xU7T^w)nq$c&6maX9@(dLynJ;-RvG^0dy{;6vcI9puKCZdG5H?lyOnP1dE?)Q zD?eW?^DKMR(!JT*@6zmLl5*}}maR?y|1vM`@Y3b~9&?{Nm-}ElvpzS|jRW~?pmp1z z$;KZy&(|G$9ru0L{VxwqE*x0jV!$!Oaxu4Jt9rvm{#U%8S(%=0e)Y+BZN^)VEW@z2 zFM4s#5f>tiI|cY=_lg!@i~rHy$8+)C#lAwZsVnWST}wBO_~jRQ?9DtmwKlemg^zx} zUSmE}MsDSWTX&q61Z@eC(6lJ2=m^?)WZz+S2}zm9YmEJlKN65)QWW%<6xAa<%`4_{ z`u{rd=W|N=WY@B`gt#PjcxG9ouTbkdZf<{W)zsQIck5>?-P`SPiL3EbWLZ#lh{PxR z|3Cjfe!ITj*8P~9<PG}+t5m!H>`77#a8jIlfU~`5*8e|8^*1_{hg&af`um&z;_eDg z+q-jJf)b`GZxvW%a85|Wb&l1NEgFgjE1fmkMeY29EndnVzrwNA;kCd+ncTImez9Ap z-S9Gd^XmD78*xI~EB$;P<@i)D>^_(xGto*Yc%j(x64UJ$E}OPT2|do@bYxg~?qZBi zVM0Zd?C#&3*_zDk-#6C(ue)WnOJenui%tcvR*9O3@4E5lg7ceOd)w8^ZGD3k6OQ#n zTBxrG4L)|P%_zN~Nkm9>@1xaQ`A<#@O7?Ne3ZBBHA<A_n$T7THSle&rdC~V(;)xN9 z0<sp`%q;rx!7(V<+5N)Ji${MPVdUGT-(Yaw@k^g_)1x2V-wa=?D>nYy=D>9}`urcm z+}1d$42HNzst?%eHm~@8=I^pI^1LP=UORC(7O!lvTJ|ySLCw$bjy2+^7ZmJJQCk_t z*{!H`#e?(Om1L_W<*{kkPS+To|MA1Z*VlJu^Nu(zu`Q(~1;;9%PxSE%SnU&FsM*LR zxbmQ-_r?{HGEzy`&Xm1Zbu`+%e0F1VyQPtZk6*?Tp$zSf=MvVIPqBJk{Y9?6hFg1@ zZdzHn_OW9vUP>uunl4%wCVlKI<ceCjMd_G;r>lZvMz3(+4U1V^mH`1hPOGMJB}Onj zH8P&->^Z-AMu@C?+i^`ZS05igA&sMv>GM79xB^-@o_~Hdr}>KHl*thfn`gFuNjwu~ zu|(Le$+e-F(~D(^nS!U5MDhfuz?o|T=gBBvzj9<#WGsu|8~OX}L6enLuFSHr?9x&( zvy3rybZ1PynmEDm>{6S|ERUrLI%P7J8>TnP-nOXtp|JV+xksk?yCkxmj!pIiop{B> z_eL_oXr7B!;|9Aqk=`qggwFY3*>WuHX8q0Ii>5ef_6A8Q>MYpvlet~>D3|N3YaNfd z77GiTh&q?(EsOD8F-uDJsFD>==OL!ucfWt!+|Vz5o-J~NMez5oWY4%Tv3dLE{e5rf z_b~JK;lfvY?&nX~&$eu#BZIVsCTPLluF}^t=FIsswQ06=#)G8|K`UQ;zPm-qu=M(} z{SH|?*VICix}~j}0w!pSObimvdg)$qRlW6!cE+LY$6PJ_XXRuCF8q=u%d}ENe9tFQ z4c&=9JLXjuOW0LNtm0fImOMu>USm`Cb+M}FXWcyI1>Q6)?H2#^<nrGwTg`=8gk~S< z2&vfISYq+8BIk7Qn;To_m+vd&J=A_vVM7MDg~u9a?FmuATc_QVoNKf1Yo=fPUZ(KX z52iRQ1Fa0$WwlGd<5R2Hr7No^o0ZP<iJE-&QtQEq&Re#bFI=1aZB68vH!r^h`>$b0 zb<FsaBHV1uq$um96~Lz=@wmXRa;nH<_jjHfmbHah_DtO88(`sfTJ+uhFABD6-+nn4 zec;Zsyf&@&Lal=q&65RG*iyQ}gr@VK^z1F2bwf4eGK-?@@3OaPpN}0E2r{bw=yYy( zh3@2&Did`kSh%<ACG{NeTUPR|<;_i9PA2)S$%RKeAEk3}JH}2AK6HG-(#)<YUm3DE znBFGGuW``mJoua^Ecx(-2NwP|d#Ab<PoJP~lDOtPZ%EVvk)9*=>WR^2jvq1>-`}XZ zbC>W9;k}Qm{=a&C-q>iF>i!1P&&&GFau+nRG3Gp2G9l;_=+t0PU-<lu$=4m2^<70~ zceMn*a9^7$nQ`n_QJw$`$I1dVMJ}gLKRYaZ3;YDsHGhA5=a`w1#dlJ?XvG=ctWB#| z6<@e@@6dyViB`L;Hz&j&TxF{L^35x@iIcP(v(woNm!7I9y|6m5Q{TS7zu(x>%yZp} zJt}DjmuW6mRu*ZNS-kjhi<d%R-L8(-e|LA^*z(j<Oh1N6>vI!Vud|S~qt+I6HH)fU z=?SYf9jk@C#m+oGFwybZ*OFl0)fSo-HBUHfW$$XJ3p6TmI133cPHiZNdpap-bM}3? zc~x1`Z{Par#9wlkXuBslM=(=;bB?7-l$U&fZq3X<k9>y$B}WT;A^%L)HXV`MN*#=i zBB!LSS`II5v+!Mc)HJHga@zTbL&Cp*OU{>2o5DB$x~{=F>G&%la$O1U=hfb+e{X9t z{Z{0T3dU~#m&(4{K5AEcGJc=8H*9lgZP__t;z`9Vd>d9Cwrcj2RV)6pOl_W-Aj=-+ zXpfhkn*<`5y||ZfbuN-&a9pwRoPkkL^7+QvC(*kMe}7MyIAh7FhZj9l1cFb>&Ml7% z4}9J8E+tDr#+&8n#jokX%&%WFos0ivIVI<ayQzUJFVl?!o*$10`}<f<l+JkYw8?-c z^KH&TtGKhLCVcJWIP|?xlhsI}gXQN62Rr$Nt3sD>ZB$CR*TmY>&u?sDbKpeB`~?^9 z-SXNO@IkzuJ&2R*Xh-M9!dX#WQ=+`qM3i!63N@D;IoB}JWc&7CA2XblBOb2^Id-A( z@rerpv5wkKUM<bF?EC?1!(P71di?V3U!CYZ8C?Orz5O3w98>2wEVKNJF7s3GE9W?; zY~pZ|`FQ2cL(Agl21XVxE0=Z#*(F^+$hgbe`e0MxH0E}`jcG@-<`^Uh_4Ia5Zc%u@ zJW|E;&}09+q}S`}S|-jZ|Ms$F;y16ko|{jKGqry4%Xn>YF453qW#KUeQ5ClbF^|&E zX!TBO@IIJ%AfeZRqjiGVT9cK<6C&E$+d3X=)pq}$ar4r_hu88>O@8e0@PMmD<^{=_ z#ePKv-}&CvKT))@zP01Q)a=anZ=6<iL<KqTV$m!<Qpmd8c4yEj;p}vs))?b+RZ3l7 z4&HY1Xc6H^UlwuoV;g67Zkfz9ubn+tW~umUh<1BCyt~(nGld~Y`dHTF1u9Wms|u$o z{0KLh`Z7!Y-!bErjRiT8Hv;cJ`njUfJAF^D<l6Lo8u!<;)$P8Z(7<bQ;Xpob*t*EG z|Nid&dxcMNgWrO_&SJ)w>2ItWd7N~lL^IYuV^O^3wD5+@l-aFQ3?kPV8X6vYaYJKe z>6Y!=f^?pB7FD+O@m!puU-0kedI#^;0JfDXm5VP*P10}=uC^9dUhJ`yQ^|4Vgyoa2 z2zdPrT2v|{DYZm1UgZ*FZgJY?<m+-`x)CRiJkj|7Z~p!VTZ+#my?=LCq+4o9xZ>K< zD>+?4Y}qQueq}7sn4Wz4;o&p0jVG`2eK~h`gS&if&*iZ7N@k{ReEdOYvX^*o2wG6; zFh|8?>L(ulzKstrx=UCTw4`cJGc+^vvYUR`it&hsWKzr5rGbwFf_yHDEEPFsxn+u- zlzXI-)0$!l=1Y~AR9egZCtJ-4@OZkJEmWex_n_0#X#(n@p9)(mm-<b*R@intdx@H& zI!~sK#g5_z-~OBhD|dE&){8m)CUWzNSuIzjn6wSo&614T(;dyx?ohpb+ova)B`*xF zN!_3RqUPlN<-a(b1O;BVnD{O~r<+}SGtT4Xan2;pEoz=ZhYZ{&UGaF-U@(7DKa<a# z2{W`_$OtNIaXD4{A|w0Ql_Q?Zs$^EP8O6SRoRYQR{;Qcv$)6nA)4$G>h`aB=42wq2 zw6k;lub;^)dw*{x>%Y{+H`g4Da?a6V<l7MZll_=vPMIO^VVMq}%tF3oox~L{-@I{A z&<sD-)7N8YW#yG5bSo+<GcRx9>aD`gUJDklxz4-fvx?%Gr<z-~P3ZAk6zse}iAh(} z-{;b`Yd%>E=Wxv`@@+|+7qqYQQIp!X_xBF>{i{0{Q><lO{^r@4;BY~<NhWJ6uNN-+ zG2yFxn6H-}hsLT24<81unV=xEP@tr2n~{y7oA<&NL(M3QmW@ly)a0LPTu+kQ|Ge&) z+p&zi{M4VH_+}OPJ}K!t!m*{8<9UZ?&B~jR`|H=3_e?PLV7j)9gHh;VyYBLH?9S4U zW3O6lxM%y;qrmI{$HVm3R?XA6vKQ2!*Si(%9=T-!|INJ<*wud>^!xDS*;<>8KMT{& z%{r(Z|J|#|_iRXRZ&A!q$>s^uZY;G}zTwuy86pc6wsLxGP;=$F|9Sdp@q!<bJHssE zzfBd>WS$iDD)gAnmJ5yh=UVa9Etu_F<G&!JZc<NSpTqM#8(BG*gj}8yGh<PUlQ;Ly z`Le-}N+UbJSxlOK_k+yGjL08PvKHL`G1Eusx!zBczzcsK)f|-ivG%ZcnUDuFC=-5m zm2g{Q`CBw3d+W-3x|*uzX1zJjF7(@JrE);yevhbT@4q4Jn#ScDeE0mmoch!*-SC=_ ztD>##-7~X{yVtGDOJUetoxZvLz1_EW_q^9exq8YsyfHf5EHLTZOydhjWfJWaI!xB) z%5n%UXi*E8wDF<gq8N`5j>3o~O?!WTyLcre>Dd{%NnX8uLBg4D&WfpdZp`$`lJT51 zK_zsF>4ar7qNYB(CN}5vuTLH`FB(r)pLfgaY!ug0rInjit|=~cVx844SJ@G?^2nab z&xM|cR_#mm@tHQ$GP%v%*`oR2&zlF%RT}qhy|=W-*+bvbGJE5-B%O%o&z~zfYIaYN z(iDmNG?_zGAmeSQ3un-ZGc^wbj26UrYKCjOII?u6CcF;&_jG>UnS;&kKjwPJpSE0Y z(Ot7rk|krVsLfLTf9IsMJ$+yO{@U~Z&Dz#05|g5Oqk@u)Hu<bz5@DM2^>2q)<yHR^ zYyPj7+x6~G#U7uXQzIjGoN#02QY^S89GkAX(pOU7e?ha2k@73Q|LR_HXC*|hoSZjX zDfhB^{e#H(XXoq^@5+X<{QdRCQ>pm&^^F^L3*Ntaz<BXO2D1we%=*=9EPvZ9is}1k z*gUE0$kLmxR+CS)I4IUElV_OM5fOZJDW?(7#9P)Ox`kn8A~$XB<d|24o}DozM(@ej z{Jm2ojnh7VdHi?Bs?^7AzCIzRO15pgblZCVwr_rqb~Ig3Ji1LxOIbOBW$oFsHb1YJ zSw%%_PCtHvRq^rU$t^ntWHaS%ZfMl#iP)UQTK?}--np1!wS)<N)svpe9CPeaSia}y z;RyGj)k>{P_U@hPwbX3}w}a=DD{CT4wZ7YY5wJB*n-t+bX-Q7Sk3cp){*5UYozlLZ zN%$-rZSi``RS%iw!_9N*UU_ZVpyKpXLPX?T)uuUy!k3Pm_b9t@=Azc0l&Ly$$2l*Y zQ*3>|+@#`bkjMSt6?0CoO{qA)){rfS_wj=Z3l;Z$|NH)9JipC>TU(!htlt0M?%3nP zIa98z3U!k8bN!XE)^H``^U(7ljHeXms%J%U@N_x+mUEfR;iaou_Fer*p{erQl#TXr zrt9{HDYk@vX;H87s=ONPJ@Kp3FFTKy2cnv<HK~|>(TnXf?#r5^^d+z8*FnwTW1Ok? zcRf+>D`ranU#mCy#K)`!L6zrXt!leMnR#XU*%)&cG_u8An_*gR_qkg9@tm)X=dSt1 zs=b!1bK+`BR<c?0Ma4x?L1zM!)dh=*ek+ZbI=>d{?zv=InmKJv%+2Fx=H&$ir+#a? z`R4Wg!#|&|Rh`J`Z}-u}-)?8`#fR)KU%W_q*TlM|v_ycz{@9wBwTqmN{&->0-o_4E zN&Z-P_Q_V?H+OEIpJ&^?^9%2E1B(idlmiz|2pFfEIzL(-#NzdH(tKuhlWSLMRJy-y z&fdM-N>U2cwbYxl*&|sqgH<gxtek&0JKu*VkNq!gPqO5mu9JTJvj68FkNr30yj0r4 zr!hU5X=#Aig=r2JJ!kJRH<thEx-wZv#*4G%irpnYZKkD$dafRhS*%LEj!RxRObYwU zlbU$2Ln3pJmc~ch8A1nBOw)e%#lE?-vw7xb>mPs8|I2snG%MqgU1Alc?3c7YVV0EF z^S>ry!jqRZ9a;9`!bFSiVz!40W|~gy8M>Z6Jpo+LgHBE5vJ!7Rbz&dWL!NUEv()~5 zjAZHgZ@6I7+dmO|9k?EuESz;DE>Mg~SJg|>%4)ZU*>;7Pp2A5nAJaV^Iyd{hxoSP_ zMXJjC78(0_S5=B?@*lk9w)Y9nd)EEOH~YbMUS6gf4$QoJas=B1)93x>ivK4R(7pQR z*NcwNUVX7S`h9++j*)Sb#ip5C8@4n#WS%&-eWIX_!tR9hqsi=VWp&rseGXv}N|cR? zT(9=_#?e3bX6nqbpI;EE-)eCFSa1L4rz_Q0hMnFb@=0R0kzwGnD<O+ww2e*7yzIgk z&AHNbU49O1Er5kV#f07Och29w|Kr*zvx@F~f57J#yQ^nepUrRno=pYcc(e*{rhnw* z=wW=^+#+~vaxC}VrAp<t|165r%O-Jk7c#~8*l|>*TuxgQ@cC7ET*I_k2RCw-y}f;U zXZk#^@@#9d(+?LO-m-m)LCD2p?M~c`Q5Nx0$7aXQ3GjG4;nMk_X^n>y52|!HELw9| zlU-wp;f*Ul=2<`ABc-k4<}jg&gXOWZu+7c;=MOG)oTm5U>7?uX#TN2jEt)wkNPVyE zX2HfMD{F6W4l;>IJjiPC+?Z!6_p&KQnLM3b1%5w^wyaH>dsM2im$z|J-4*$|M_q<$ z%Hei5BvqVJxaJ#5Jf7<I!D~Sv<H|;dRu6U!$44?MeMPBEv#*?Rj}_tK7i4SxS9s-d z@sZ-yjps9kEO$!X2()T_TD-2J@%|dNfB6p0kYY1>PT@Q46Hkj%a(`XPO08LW?f+Hj zf5J1T%C#PfdOp3CNj!b3xvvDv%&HfsXS-)-*NJTiVS1?YJpM;lj#SH$8!SCb)~=o! z``21hKG*FTlTM$PZrZs!m1kbg^_IxkX7^KM^6fGMJBvmhmaUy!%8QeA;_R3;Ma$Ri z@4jF8G<&9Py4vpVZx)5E+*ou~v&Wy$DCPK#-R~8Q)5|6t6J2sXxlw1sjl_u>J-!B> zXO28s@}6t+z0}<=KdRr{U9MkSTf4;5N0DRYQqA4vdFf%{=H1WE9+YepYbx666TGrx z@`EMiTGxL|E)7|7>;a3%l_}acCB1uGBbfQJJf@h=%aDGq-WoCg_jB)6hE6OjR!KQY zlYIGYy=1~?>`stNpHnNfP?%%wipZ1q4!39MZk>2~dPcVwi<bM%P>*a=mn_4Glof>% zLX!oedkfW0yKR{_XQz%8Te~sa6a~L*iR4XdJi51@n{B<pV`(k_0$W2iw!VAQPrLtX zcVF5jV5jHa)v#mMhSbN-Yix2&@A~rlXkWgjEB~*(vm(v(gQc&M`l?1JjdRg;d*5%* zS<v_#7FphBW*JYf{QP{<ES5R06DFx>CI}w-bs*_sXZIzkp8k&v@nUWq>lawQOpcuL zUVQV-4s*@c`C)<jwN?jLT@Jr!x>$O)O2g;9>7C9QC*QPguKe|KuTIPrZ-tLsOGG4Q zC+VD-XWoBM*;(dhVM9%EWA(Os-J2%;d+VP(dCInVGfU2ABv&N0{Fbkn@bq+8!c+x$ z(U<Q6a_;Y*Z_C_1<L>3wt%fPjxD#vc&(hEREivuewX#Ve22ra&9?-A%+qk)R4qwF1 z9Le(g<?`))Je#t=`#ribaarh^sUDnB?L57G8)_a3Z3(ioa;-R&!>GA=pVjh>R|<lZ za>b_Uh#YD>nAGcL<(?&b$x^6O-P$Pl_L7v0k~z82a*kPN58bmoGvAo`p-SegB!PYN z^?%>Vnrf6dWwGTc!`(|KTg-J);q>F^Db09Y%{f;@<=Dh1=M^kok9v*xVzLTO?RP&W zQM6OW&*FdO<M-QVS}t3sCHJ;`&Hn9tv(L63i_p4i^mCa~kY`Bjy2)Zw+%#Uis}fM$ zGr6K_{k@GYA67_lT<(mE-CMVBqM`P)fBd(+PsdMrAI`l0Z-&4DHmQsUsqF?lmT!A5 z8+z(0XVlruGIX!r-m-mJlW_vCm*@K>Q|y+xSakaaw{QqVrS<u>J1DliSDwNoAOGkN z%Y@74VtS`BDT^NBWRjea)m+FKC~@gZ+@lBo4xgEIzfqAb+rep$N?n&nx;nG}`&7Sb z<HO3yA?mA5e0zjhW*selzB&20A0LlgLQYN7$BBaP_P&o}TB|AAH6?1cq>aUi2QOG; zS$$urc>PX3+9-N#cKC!dvyI!;x8*-RaL{?qx30|_u5EgGF>pzNPTZD`-S79#P7*1+ zsIC9#-f#H>w<JVcj+m)-2G5$s)Z@ER&rRu~(}WpUCR?yilSrR(ew#3#V(^k+3*8N7 zOCOlHWs8Ict?Zn0*u#B^GM}8qp=ryvEiB%Ub5hBw>K13qfmtGdHvgQoyTF2H>Z-)& z2g<^>Z<*Y!w5#i_%nS<`E!k_DTZH%hH=Ools=|b>2)23h(ocI0q9$0qt^U)(thypp zXiDn=>!1k@1$@~lWqg_f`<7oxGc-Tdul%vA;M-xPl}9a}7@qM}T(K#q&O`6ktL^K* zFY$YQ^|YD28*j_Y)Q9n^M$0tqyMx95UF`nCoBiNFn+Zn(Gq1^qO@}kn=eg;L|G2k( z&5`FH7GGX-_KMK+&Usr`hS#g?IIzei>|XJYm!g;0#j>Anek&7as}j5~#m(*7I%{!V zQ7?(0mj-&SyXNrE+P1Ic#@)MT*Dc>Zc}jEvV~f&)w4``Dw*VctH?~`*|C{@FN$1I? zNvu&04U6+{8h!hl)DT*`+Vb}qQ=cQLeDab>2@e?D%VZQMFh>9WJ@e}2!;O2ZU%r^> zSiH|6I$FCmrt!v-H@CO<^Uj{96w-D5|2geKzIT-w%xiOXr%cxR&ChFK7MJ?+4=c;8 z|MT~n_fC9cv)*KW{!a6}oSpBt>g!xPwo0kn+BI;QM&LHpNZoFu+h%)`#7fN5c3nJ> z&=9%nA=|U(e`X)$HL=M^xbtq>EoJ^&n^I3s(uka<QJAiqQn)hd?aauXF2}0gZ$I1r zJ}qqGqLj*AIwu2U8m9K_h@3f5u<-RfoA=e{9Mes!=JGB}TfVcVa$;22(Wq`A!&p6* z_Toirj(*NqtJ&n5C8_M^bZ7cxr-!y2lI6^;LLBoKec)KRV`EM8_Ip*0F6uJYd-^xd zEZm~$YP|A-#-0xqiW?42obpyp$%9LngJ*(L@}kIe#rcot9xYF*=@#k`aM1q1_*&Pf zmuv2X#t;>ag#{5J6RM?qO_cgJ|8|WOSMOZn=kRdRq1~Q;78zRz9h6{IE>Lu1@tmp9 zq9ka@b6dLk8t3hAbM98{-<SQpU*3^d=l!2VwTa(XHS*v2sefTr)o#Cyigj!TDh<v& zhDYve>*T~I9AEdgLO$uW%MF>vTN12?biF#uE1nnZ+w(!_`-LSviw}Fvdem`N!7;}y zI-pImSvl>5tZm(lUpF+)RWB)LS-#=mgC3n^2OBdBldh9DJ?~Zhmi=~rqqw&0f)D2& ztXU8#|Mb`^E%SA2gP*WQW%isr$hq(DpYIhP-<<x^yHxM>9IMi{ti^|p{LtV&-Y3ws zSc9wS(w<MRBGa~=zxe)XOibLPS4C|On>Ot`Wi76^q4v66*EcrvX<{p{X6xwb8d@74 zm9Ks0e<P!O!huJhw5+3LT|S63%cRS!-71!RcH-JBLq(Nyw<UCiL_8Wx%e3?Lf81EC zo%+Y-z3su>pMI7u@ti7co>%Z{>*gz3qVH_B%-?xZa!;q@=@VzK>pcjVm?JdR=eZ(F zBhS3NyqyIfg{sTauWZt~eAe?^d^Nk`qEp(;JijcJB-}O$&iTxu`Jr`b{F9C)TtZ8} zcpR|yPxM{0I9SukCB0yRlH08*$^X~JIOO#;%q?yaIN{qUv>>EuBj1Gz2i6}KCbLFf z&0SgC@qL2LKQ_}3?gpKAR<XUC`P+hfa{rxq!Z{uDC3!d>2srb6{LYp+tLS{K`l-`T z&T6MKtl^EwR%Q&8Qd9|WVA%cChBvz2*K4QhQ4Y<IExLytVwijWUFhsI?3=r%``m*5 zFY_4L1cNU5Jp2%mUZ^+AO=p_d(mo&4?r`y$Gv;>OELSSK9u*wmY2?)LyV=W&EBHan zfihcOna{=CHxeS_A`=U84;<jh*nW-E@j}kEnR8^8$H_na^we9%vS32aZJY4$X_m#` zbot)gKd;PhcO+}|QSbBn58Nz%eqz#;ZgKshhksmaCRn5gUiy40d;P{;`%Yas!}D{2 zLd6SyuCjAy6r4NKBt;kdas<|PrKl}X?mfgE;IyDdp?uq!jocCGFP_x;&9CK5<}JUo zasJEB!X--2{;y<NY2(;9Nh^(q%hf?)uR8~C(A4z{)j9n4Z{S$;d;3hY84`07w(e~! z-D~mg`-3^hZ#o1RPPoP9948Wz(j+kJ&a4|YMjw`R9-6Z7*1gCrU0+UHM8CV<y6K=x z&cu+VAvbsP7`ks_5d8e#r^8VHH~*nn^)ui5Gq?LFY!ByMqq2C;p5z<1?T*}+b7rzQ zBH;XI@4?Q=>L)g3?fKE_vCFB$P<36-n~uB_5;wGC78p!ZP`PK_viXEcuM103YOBao z4~w{fz2+6{N}bgy@>OpfT?!<!BVU(lHmM4VO6}_^7JI(fdC?-#$`hRX4xPJOJg4fT z=`nTn30{Ir4nL~=+*^F(&cdn3*rcmdbtT?=wmMauyxZQlDf_(Mgu*M&=Q?M5K9pJg zIy-00+M>U|N`3NvzA~S;H1PC}ikCKV%UJSXY`K=vXF7A<%+##3mex+zdwaHUI9<rg zzwny>1Up-7=$gDOndQIU%$TpVG9)r8^5MS2?1BxG6nAAh&$M2_<l)XSNr8D*!z3wr zg^nOeR<74OKb%wbn`?WR`TO0&@80fC(r)MJSn%;&gII++$Dv%??@qfeU0@FCl(-;! z;PeZQyzgvl^41tfuQs}MB0^$zdSR_(x^9rCiqO)arU@cu>Kz#`JVV$nJ?J^iD&4E# zXmlcZ>s+m;mWnPi(!$%WY(0B%{gg>6o{Kg|bWCFL`gEs><06Ao	kJg3VvvU3*vN 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 Sq!<_&7(8A5T-G@yGywpksKk5# literal 0 HcmV?d00001 diff --git a/Vagrant Files/files/scyther/Protocols/Demo/ns3.spdl b/Vagrant Files/files/scyther/Protocols/Demo/ns3.spdl new file mode 100644 index 0000000..c9235c5 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/Demo/ns3.spdl @@ -0,0 +1,41 @@ +/* + * Needham-Schroeder protocol + */ + +// The protocol description + +protocol ns3(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {I,ni}pk(R) ); + recv_2(R,I, {ni,nr}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {I,ni}pk(R) ); + send_2(R,I, {ni,nr}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} + + + diff --git a/Vagrant Files/files/scyther/Protocols/Demo/nsl3-broken.spdl b/Vagrant Files/files/scyther/Protocols/Demo/nsl3-broken.spdl new file mode 100644 index 0000000..c635f91 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/Demo/nsl3-broken.spdl @@ -0,0 +1,40 @@ +/* + * Needham-Schroeder-Lowe protocol, + * broken version (wrong role name in first message) + */ + +// The protocol description + +protocol nsl3-broken(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {R,ni}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {R,ni}pk(R) ); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/Demo/nsl3-updated-both.spdl b/Vagrant Files/files/scyther/Protocols/Demo/nsl3-updated-both.spdl new file mode 100644 index 0000000..076166e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/Demo/nsl3-updated-both.spdl @@ -0,0 +1,78 @@ +/* + * Needham-Schroeder-Lowe protocol, + * broken version (wrong role name in first message) + */ + +// The protocol description + +protocol nsl3-broken(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {R,ni}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {R,ni}pk(R) ); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} + +/* + * Needham-Schroeder-Lowe protocol + */ + +// The protocol description + +protocol nsl3(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {I,ni}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {I,ni}pk(R) ); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/Demo/nsl3.spdl b/Vagrant Files/files/scyther/Protocols/Demo/nsl3.spdl new file mode 100644 index 0000000..ebf9031 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/Demo/nsl3.spdl @@ -0,0 +1,38 @@ +/* + * Needham-Schroeder-Lowe protocol + */ + +// The protocol description + +protocol nsl3(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {I,ni}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {I,ni}pk(R) ); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2rsa.spdl b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2rsa.spdl new file mode 100644 index 0000000..73133a7 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2rsa.spdl @@ -0,0 +1,46 @@ +/* + * PKMv2-RSA + * + * Initial model by: Sjouke Mauw, Sasa Radomirovic (2007) + * Model changes: Cas Cremers (Nov 2012) + * + * Analysed in: "A framework for compositional verification of security protocols" + * With S. Andova, K. Gjosteen, S. Mauw, S. Mjolsnes, and S. Radomirovic. + * Information and Computation, Special issue on Computer Security: + * Foundations and Automated Reasoning, Volume 206, Issues 2-4, pp. 425-459, + * Elsevier, 2008. + */ + +// The protocol description + +protocol pkmv2rsa(MS,BS) +{ + role MS + { + fresh msrand, said: Nonce; + var prepak, bsrand: Nonce; + + send_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + recv_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + send_rsa3(MS,BS, {bsrand}sk(MS) ); + + claim_rsai3(MS,Niagree); + claim_rsai4(MS,Nisynch); + claim_rsai5(MS,SKR,prepak); + } + + role BS + { + var msrand, said: Nonce; + fresh prepak, bsrand: Nonce; + + recv_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + send_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + recv_rsa3(MS,BS, {bsrand}sk(MS) ); + + claim_rsar3(BS,Niagree); + claim_rsar4(BS,Nisynch); + claim_rsar5(BS,SKR,prepak); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2rsacorrected.spdl b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2rsacorrected.spdl new file mode 100644 index 0000000..4bd5205 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2rsacorrected.spdl @@ -0,0 +1,46 @@ +/* + * PKMv2-RSA + * + * Initial model by: Sjouke Mauw, Sasa Radomirovic (2007) + * Model changes: Cas Cremers (Nov 2012) + * + * Analysed in: "A framework for compositional verification of security protocols" + * With S. Andova, K. Gjosteen, S. Mauw, S. Mjolsnes, and S. Radomirovic. + * Information and Computation, Special issue on Computer Security: + * Foundations and Automated Reasoning, Volume 206, Issues 2-4, pp. 425-459, + * Elsevier, 2008. + */ + +// The protocol description + +protocol pkmv2rsa(MS,BS) +{ + role MS + { + fresh msrand, said: Nonce; + var prepak, bsrand: Nonce; + + send_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + recv_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + send_rsa3(MS,BS, {bsrand,BS}sk(MS) ); + + claim_rsai3(MS,Niagree); + claim_rsai4(MS,Nisynch); + claim_rsai5(MS,SKR,prepak); + } + + role BS + { + var msrand, said: Nonce; + fresh prepak, bsrand: Nonce; + + recv_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + send_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + recv_rsa3(MS,BS, {bsrand,BS}sk(MS) ); + + claim_rsar3(BS,Niagree); + claim_rsar4(BS,Nisynch); + claim_rsar5(BS,SKR,prepak); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2satek.spdl b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2satek.spdl new file mode 100644 index 0000000..b166a1b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pkmv2satek.spdl @@ -0,0 +1,63 @@ +/* + * PKMv2-SA-TEK + * + * Initial model by: Sjouke Mauw, Sasa Radomirovic (2007) + * Model changes: Cas Cremers (Nov 2012) + * + * Analysed in: "A framework for compositional verification of security protocols" + * With S. Andova, K. Gjosteen, S. Mauw, S. Mjolsnes, and S. Radomirovic. + * Information and Computation, Special issue on Computer Security: + * Foundations and Automated Reasoning, Volume 206, Issues 2-4, pp. 425-459, + * Elsevier, 2008. + */ + +// Setup + +hashfunction hash; +hashfunction prepak; +const akid; +const u,d; + +// The protocol description + +protocol pkmv2satek(MS,BS) +{ + role MS + { + fresh msrand': Nonce; + var bsrand', tek0, tek1: Nonce; + + recv_satek1(BS,MS, bsrand',akid, + hash(d,prepak(MS,BS),BS,MS,bsrand',akid) ); + send_satek2(MS,BS, msrand',bsrand',akid, + hash(u,prepak(MS,BS),BS,MS,msrand',bsrand',akid) ); + recv_satek3(BS,MS, + msrand',bsrand',akid,{tek0,tek1}hash(prepak(MS,BS)), + hash(d,prepak(MS,BS),msrand',bsrand',akid,{tek0,tek1}hash(prepak(MS,BS)))); + + claim_rsai3(MS,Niagree); + claim_rsai4(MS,Nisynch); + claim_rsai6(MS,SKR,tek0); + claim_rsai7(MS,SKR,tek1); + } + + role BS + { + var msrand': Nonce; + fresh bsrand', tek0, tek1: Nonce; + + send_satek1(BS,MS, bsrand',akid, + hash(d,prepak(MS,BS),BS,MS,bsrand',akid) ); + recv_satek2(MS,BS, msrand',bsrand',akid, + hash(u,prepak(MS,BS),BS,MS,msrand',bsrand',akid) ); + send_satek3(BS,MS, + msrand',bsrand',akid,{tek0,tek1}hash(prepak(MS,BS)), + hash(d,prepak(MS,BS),msrand',bsrand',akid,{tek0,tek1}hash(prepak(MS,BS)))); + + claim_rsar3(BS,Niagree); + claim_rsar4(BS,Nisynch); + claim_rsar6(BS,SKR,tek0); + claim_rsar7(BS,SKR,tek1); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pqr.spdl b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pqr.spdl new file mode 100644 index 0000000..731d369 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/pqr.spdl @@ -0,0 +1,84 @@ +/* + * PKMv2-RSA + * + * Initial model by: Sjouke Mauw, Sasa Radomirovic (2007) + * Model changes: Cas Cremers (Nov 2012) + * + * Analysed in: "A framework for compositional verification of security protocols" + * With S. Andova, K. Gjosteen, S. Mauw, S. Mjolsnes, and S. Radomirovic. + * Information and Computation, Special issue on Computer Security: + * Foundations and Automated Reasoning, Volume 206, Issues 2-4, pp. 425-459, + * Elsevier, 2008. + */ + +// Setup + +hashfunction hash; +hashfunction prepak; +const akid; +const u,d; + +// The protocol description + +protocol rsaplussatek(MS,BS) + +{ + role MS + { + fresh msrand, msrand', said, c: Nonce; + var prepak, bsrand, bsrand', tek0, tek1, tek2, tek3: Nonce; + + send_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + recv_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + send_rsa3(MS,BS, {bsrand, BS}sk(MS) ); + + recv_satek1(BS,MS, bsrand',akid, + hash(d,prepak,BS,MS,bsrand',akid) ); + send_satek2(MS,BS, msrand',bsrand',akid, + hash(u,prepak,BS,MS,msrand',bsrand',akid) ); + recv_satek3(BS,MS, + msrand',bsrand',akid,{tek0,tek1}hash(prepak), + hash(d,prepak,msrand',bsrand',akid,{tek0,tek1}hash(prepak))); + + send_tekup1(MS,BS,{c}hash(prepak)); + recv_tekup2(BS,MS,{c,tek2,tek3}hash(prepak)); + + claim_rsai3(MS,Niagree); + claim_rsai4(MS,Nisynch); + claim_rsai5(MS,SKR,prepak); + claim_rsai6(MS,SKR,tek0); + claim_rsai7(MS,SKR,tek1); + claim_rsar8(MS,SKR,tek2); + claim_rsar9(MS,SKR,tek3); + } + + role BS + { + var msrand, msrand', said, c: Nonce; + fresh prepak, bsrand, bsrand', tek0, tek1, tek2, tek3: Nonce; + + recv_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + send_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + recv_rsa3(MS,BS, {bsrand, BS}sk(MS) ); + + send_satek1(BS,MS, bsrand',akid, + hash(d,prepak,BS,MS,bsrand',akid) ); + recv_satek2(MS,BS, msrand',bsrand',akid, + hash(u,prepak,BS,MS,msrand',bsrand',akid) ); + send_satek3(BS,MS, + msrand',bsrand',akid,{tek0,tek1}hash(prepak), + hash(d,prepak,msrand',bsrand',akid,{tek0,tek1}hash(prepak))); + + recv_tekup1(MS,BS,{c}hash(prepak)); + send_tekup2(BS,MS,{c,tek2,tek3}hash(prepak)); + + claim_rsar3(BS,Niagree); + claim_rsar4(BS,Nisynch); + claim_rsar5(BS,SKR,prepak); + claim_rsar6(BS,SKR,tek0); + claim_rsar7(BS,SKR,tek1); + claim_rsar8(BS,SKR,tek2); + claim_rsar9(BS,SKR,tek3); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/rsaplussatek.spdl b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/rsaplussatek.spdl new file mode 100644 index 0000000..eb15dde --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/rsaplussatek.spdl @@ -0,0 +1,74 @@ +/* + * PKMv2-RSA + * + * Initial model by: Sjouke Mauw, Sasa Radomirovic (2007) + * Model changes: Cas Cremers (Nov 2012) + * + * Analysed in: "A framework for compositional verification of security protocols" + * With S. Andova, K. Gjosteen, S. Mauw, S. Mjolsnes, and S. Radomirovic. + * Information and Computation, Special issue on Computer Security: + * Foundations and Automated Reasoning, Volume 206, Issues 2-4, pp. 425-459, + * Elsevier, 2008. + */ + +// Setup + +hashfunction hash; +hashfunction prepak; +const akid; +const u,d; + +// The protocol description + +protocol rsaplussatek(MS,BS) + +{ + role MS + { + fresh msrand, msrand', said: Nonce; + var prepak, bsrand, bsrand', tek0, tek1: Nonce; + + send_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + recv_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + send_rsa3(MS,BS, {bsrand}sk(MS) ); + + recv_satek1(BS,MS, bsrand',akid, + hash(d,prepak,BS,MS,bsrand',akid) ); + send_satek2(MS,BS, msrand',bsrand',akid, + hash(u,prepak,BS,MS,msrand',bsrand',akid) ); + recv_satek3(BS,MS, + msrand',bsrand',akid,{tek0,tek1}hash(prepak), + hash(d,prepak,msrand',bsrand',akid,{tek0,tek1}hash(prepak))); + + claim_rsai3(MS,Niagree); + claim_rsai4(MS,Nisynch); +// claim_rsai5(MS,SKR,prepak); +// claim_rsai6(MS,SKR,tek0); +// claim_rsai7(MS,SKR,tek1); + } + + role BS + { + var msrand, msrand', said: Nonce; + fresh prepak, bsrand, bsrand', tek0, tek1: Nonce; + + recv_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + send_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + recv_rsa3(MS,BS, {bsrand}sk(MS) ); + + send_satek1(BS,MS, bsrand',akid, + hash(d,prepak,BS,MS,bsrand',akid) ); + recv_satek2(MS,BS, msrand',bsrand',akid, + hash(u,prepak,BS,MS,msrand',bsrand',akid) ); + send_satek3(BS,MS, + msrand',bsrand',akid,{tek0,tek1}hash(prepak), + hash(d,prepak,msrand',bsrand',akid,{tek0,tek1}hash(prepak))); + + claim_rsar3(BS,Niagree); + claim_rsar4(BS,Nisynch); +// claim_rsar5(BS,SKR,prepak); +// claim_rsar6(BS,SKR,tek0); +// claim_rsar7(BS,SKR,tek1); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/rsaplussatekcorrected.spdl b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/rsaplussatekcorrected.spdl new file mode 100644 index 0000000..b8051d8 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IEEE-WIMAX/rsaplussatekcorrected.spdl @@ -0,0 +1,73 @@ +/* + * PKMv2-RSA + * + * Initial model by: Sjouke Mauw, Sasa Radomirovic (2007) + * Model changes: Cas Cremers (Nov 2012) + * + * Analysed in: "A framework for compositional verification of security protocols" + * With S. Andova, K. Gjosteen, S. Mauw, S. Mjolsnes, and S. Radomirovic. + * Information and Computation, Special issue on Computer Security: + * Foundations and Automated Reasoning, Volume 206, Issues 2-4, pp. 425-459, + * Elsevier, 2008. + */ + +// Setup + +hashfunction hash; +hashfunction prepak; +const akid; +const u,d; + +// The protocol description + +protocol rsaplussatek(MS,BS) + +{ + role MS + { + fresh msrand, msrand', said: Nonce; + var prepak, bsrand, bsrand', tek0, tek1: Nonce; + + send_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + recv_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + send_rsa3(MS,BS, {bsrand, BS}sk(MS) ); + + recv_satek1(BS,MS, bsrand',akid, + hash(d,prepak,BS,MS,bsrand',akid) ); + send_satek2(MS,BS, msrand',bsrand',akid, + hash(u,prepak,BS,MS,msrand',bsrand',akid) ); + recv_satek3(BS,MS, + msrand',bsrand',akid,{tek0,tek1}hash(prepak), + hash(d,prepak,msrand',bsrand',akid,{tek0,tek1}hash(prepak))); + + claim_rsai3(MS,Niagree); + claim_rsai4(MS,Nisynch); + claim_rsai5(MS,SKR,prepak); + claim_rsai6(MS,SKR,tek0); + claim_rsai7(MS,SKR,tek1); + } + + role BS + { + var msrand, msrand', said: Nonce; + fresh prepak, bsrand, bsrand', tek0, tek1: Nonce; + + recv_rsa1(MS,BS, {msrand, said, MS}sk(MS) ); + send_rsa2(BS,MS, {msrand, bsrand,{prepak,MS}pk(MS),BS}sk(BS) ); + recv_rsa3(MS,BS, {bsrand, BS}sk(MS) ); + + send_satek1(BS,MS, bsrand',akid, + hash(d,prepak,BS,MS,bsrand',akid) ); + recv_satek2(MS,BS, msrand',bsrand',akid, + hash(u,prepak,BS,MS,msrand',bsrand',akid) ); + send_satek3(BS,MS, + msrand',bsrand',akid,{tek0,tek1}hash(prepak), + hash(d,prepak,msrand',bsrand',akid,{tek0,tek1}hash(prepak))); + + claim_rsar3(BS,Niagree); + claim_rsar4(BS,Nisynch); + claim_rsar5(BS,SKR,prepak); + claim_rsar6(BS,SKR,tek0); + claim_rsar7(BS,SKR,tek1); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/Makefile b/Vagrant Files/files/scyther/Protocols/IKE/Makefile new file mode 100644 index 0000000..7234a64 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/Makefile @@ -0,0 +1,11 @@ +CPPSRC= $(wildcard *.cpp) +DEST= $(CPPSRC:.cpp=.spdl) + +default: $(DEST) + +%.spdl: %.cpp + cpp $< >$@ + +mpa: $(DEST) make-mpa.py + ./make-mpa.py + diff --git a/Vagrant Files/files/scyther/Protocols/IKE/common.h b/Vagrant Files/files/scyther/Protocols/IKE/common.h new file mode 100644 index 0000000..6dcb5d2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/common.h @@ -0,0 +1,157 @@ +/**************************************************************************** + * THIS FILE CONTAINS DEFINITIONS OF COMMON MACROS AND TYPES * + ****************************************************************************/ + + hashfunction prf, KDF; + +/********************************** + * DIFFIE-HELLMAN ABSTRACTIONS * + * Zi = Gr^i = g^(ri) + * Zr = Gi^r = g^(ir) + **********************************/ +const g, h: Function; +#define Zi h(Gr,i) +#define Zr h(Gi,r) + +/********************************** + * PROTOCOL DEPENDENT DEFINITIONS * + **********************************/ +#ifdef __IKEV1__ +hashfunction H; +#define SKi KDF(Ni, Nr, Zi, Ci, Cr) +#define SKr KDF(Ni, Nr, Zr, Ci, Cr) +#endif + +#ifdef __IKEV1_PSK__ +#define SKi prf(k(I,R), Ni, Nr, Zi, Ci, Cr) +#define SKr prf(k(R,I), Ni, Nr, Zr, Ci, Cr) +#endif + +#ifdef __IKEV1_QUICK__ +/* k(.,.) equals Kd from the spec */ +#define SKi KDF(k(I,R),Zi,Ni,Nr) +#define SKr KDF(k(R,I),Zr,Ni,Nr) +#endif + +#ifdef __IKEV1_QUICK_NOPFS__ +/* k(.,.) equals Kd from the spec */ +#define SKi KDF(k(I,R),Ni,Nr) +#define SKr KDF(k(R,I),Ni,Nr) +#endif + +#ifdef __IKEV2__ +hashfunction MAC; +#define HDR (SPIi,SPIr) +#define SKi KDF(Ni,Nr,Zi,SPIi,SPIr) +#define SKr KDF(Ni,Nr,Zr,SPIi,SPIr) +#endif + +#ifdef __IKEV2_CHILD__ +#define SKi KDF(k(I,R),Zi,Ni,Nr) +#define SKr KDF(k(R,I),Zr,Ni,Nr) +#endif + +#ifdef __IKEV2_CHILD_NOPFS__ +#define SKi KDF(k(I,R),Ni,Nr) +#define SKr KDF(k(R,I),Ni,Nr) +#endif + +#ifdef __JFK_CORE__ +hashfunction H; +#define SKi KDF(Zi, Ni, Nr) +#define SKr KDF(Zr, Ni, Nr) +#endif + +#ifdef __JFK__ +hashfunction H; +#define SKi KDF(Zi, H(Ni), Nr) +#define SKr KDF(Zr, H(Ni), Nr) +#endif + +#ifdef __OAKLEY__ +#define SKi KDF(Ni, Nr, Zi, Ci, Cr) +#define SKr KDF(Ni, Nr, Zr, Ci, Cr) +#endif + +#ifdef __OAKLEY_CONSERVATIVE__ +#define SKi KDF(Ni, Nr, Zi, Ci, Cr) +#define SKr KDF(Ni, Nr, Zr, Ci, Cr) +#endif + +#ifdef __SKEME__ +#define SKi KDF(Zi) +#define SKr KDF(Zr) +#endif + +#ifdef __SKEME_REKEY__ +#define SKi KDF(k(I,R),prf(k(I,R), Ni, Nr, R, I)) +#define SKr KDF(k(R,I),prf(k(R,I), Ni, Nr, R, I)) +#endif + +#ifdef __STS__ +#define SKi KDF(Zi) +#define SKr KDF(Zr) +hashfunction MAC; +#endif + +protocol @oracle (DH, SWAP) { +#define Gi g(i) +#define Gr g(r) + + /* Diffie-Hellman oracle: If the adversary is in possession of g^xy, he + * can obtain g^yx. + * @obsolete The adversary does not need DH as long as SWAP exists + */ + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, Zi ); + send_!DH2( DH, DH, Zr ); + } + + /* Session key swap oracle: If the adversary is in possession of eg the + * initiators session key, he can obtain the responders session key. + */ + role SWAP { + var i, r, Ni, Nr: Nonce; + +#ifdef __IKEV1__ + var Ci, Cr: Nonce; +#endif +#ifdef __IKEV1_PSK__ + var Ci, Cr: Nonce; + var I, R: Agent; +#endif +#ifdef __IKEV1_QUICK__ + var I, R: Agent; +#endif +#ifdef __IKEV1_QUICK_NOPFS__ + var I, R: Agent; +#endif +#ifdef __IKEV2__ + var SPIi, SPIr: Nonce; +#endif +#ifdef __IKEV2_CHILD__ + var I, R: Agent; +#endif +#ifdef __IKEV2_CHILD_NOPFS__ + var I, R: Agent; +#endif +#ifdef __OAKLEY__ + var Ci, Cr: Nonce; +#endif +#ifdef __OAKLEY_CONSERVATIVE__ + var Ci, Cr: Nonce; +#endif +#ifdef __SKEME_REKEY__ + var I, R: Agent; +#endif + + recv_!SWAP1( SWAP, SWAP, SKi ); + send_!SWAP2( SWAP, SWAP, SKr ); + + } +#undef Gi +#undef Gr +} +#define __ORACLE__ \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a1.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a1.cpp new file mode 100644 index 0000000..86947a8 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a1.cpp @@ -0,0 +1,96 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Public key authentication (aggressive mode), + * last message not encrypted + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define HASH1 H(CERT(R)) + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, HASH_Rr ); + send_!O2( O, O, HASH_Ri ); + + // msg 3 + recv_!O3( O, O, HASH_Ii ); + send_!O4( O, O, HASH_Ir ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-pk-a1(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), {I}pk(R), {Ni}pk(R) ); + recv_!2( R, I, Ci, Cr, algo, Gr, {R}pk(I), {Nr}pk(I), HASH_Ri ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, HASH_Ii ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, {I}pk(R), {Ni}pk(R) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, g(r), {R}pk(I), {Nr}pk(I), HASH_Rr ); + recv_!3( I, R, Ci, Cr, HASH_Ir ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a1.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a1.spdl new file mode 100644 index 0000000..b9b8f00 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a1.spdl @@ -0,0 +1,129 @@ +# 1 "ikev1-pk-a1.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk-a1.cpp" +# 17 "ikev1-pk-a1.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-pk-a1.cpp" 2 +# 27 "ikev1-pk-a1.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R) ); + send_!O2( O, O, prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R) ); + + + recv_!O3( O, O, prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I) ); + send_!O4( O, O, prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I) ); + + } + + +} + + +protocol ikev1-pk-a1(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), {I}pk(R), {Ni}pk(R) ); + recv_!2( R, I, Ci, Cr, algo, Gr, {R}pk(I), {Nr}pk(I), prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, {I}pk(R), {Ni}pk(R) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, g(r), {R}pk(I), {Nr}pk(I), prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R) ); + recv_!3( I, R, Ci, Cr, prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a12.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a12.cpp new file mode 100644 index 0000000..435479a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a12.cpp @@ -0,0 +1,95 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Public key authentication (aggressive mode), + * last message encrypted + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define HASH1 H(CERT(R)) + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, HASH_Rr ); + send_!O2( O, O, HASH_Ri ); + + // msg 3 + recv_!O3( O, O, {HASH_Ii}SKi ); + send_!O4( O, O, {HASH_Ir}SKr ); + + } +#undef Gi +#undef Gr +} + +protocol ikev1-pk-a12(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), {I}pk(R), {Ni}pk(R) ); + recv_!2( R, I, Ci, Cr, algo, Gr, {R}pk(I), {Nr}pk(I), HASH_Ri ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, {HASH_Ii}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, {I}pk(R), {Ni}pk(R) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, g(r), {R}pk(I), {Nr}pk(I), HASH_Rr ); + recv_!3( I, R, Ci, Cr, {HASH_Ir}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a12.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a12.spdl new file mode 100644 index 0000000..473ffc7 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a12.spdl @@ -0,0 +1,128 @@ +# 1 "ikev1-pk-a12.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk-a12.cpp" +# 17 "ikev1-pk-a12.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-pk-a12.cpp" 2 +# 27 "ikev1-pk-a12.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R) ); + send_!O2( O, O, prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R) ); + + + recv_!O3( O, O, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O4( O, O, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} + +protocol ikev1-pk-a12(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), {I}pk(R), {Ni}pk(R) ); + recv_!2( R, I, Ci, Cr, algo, Gr, {R}pk(I), {Nr}pk(I), prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, {I}pk(R), {Ni}pk(R) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, g(r), {R}pk(I), {Nr}pk(I), prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R) ); + recv_!3( I, R, Ci, Cr, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a2.cpp new file mode 100644 index 0000000..b149cfe --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a2.cpp @@ -0,0 +1,97 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Public key authentication (aggressive mode), + * last message not encrypted, nonce and id encrypted + * together + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define HASH1 H(CERT(R)) + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, HASH_Rr ); + send_!O2( O, O, HASH_Ri ); + + // msg 3 + recv_!O3( O, O, HASH_Ii ); + send_!O4( O, O, HASH_Ir ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-pk-a2(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), {I,Ni}pk(R) ); + recv_!2( R, I, Ci, Cr, algo, Gr, {R,Nr}pk(I), HASH_Ri ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, HASH_Ii ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, {I,Ni}pk(R) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, g(r), {R,Nr}pk(I), HASH_Rr ); + recv_!3( I, R, Ci, Cr, HASH_Ir ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a2.spdl new file mode 100644 index 0000000..60b9fb4 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a2.spdl @@ -0,0 +1,129 @@ +# 1 "ikev1-pk-a2.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk-a2.cpp" +# 18 "ikev1-pk-a2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 19 "ikev1-pk-a2.cpp" 2 +# 28 "ikev1-pk-a2.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R) ); + send_!O2( O, O, prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R) ); + + + recv_!O3( O, O, prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I) ); + send_!O4( O, O, prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I) ); + + } + + +} + + +protocol ikev1-pk-a2(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), {I,Ni}pk(R) ); + recv_!2( R, I, Ci, Cr, algo, Gr, {R,Nr}pk(I), prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, {I,Ni}pk(R) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, g(r), {R,Nr}pk(I), prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R) ); + recv_!3( I, R, Ci, Cr, prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a22.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a22.cpp new file mode 100644 index 0000000..a71e20a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a22.cpp @@ -0,0 +1,95 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Public key authentication (aggressive mode), + * last message encrypted, nonce and id encrypted together + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define HASH1 H(CERT(R)) + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, HASH_Rr ); + send_!O2( O, O, HASH_Ri ); + + // msg 3 + recv_!O3( O, O, {HASH_Ii}SKi ); + send_!O4( O, O, {HASH_Ir}SKr ); + + } +#undef Gi +#undef Gr +} + +protocol ikev1-pk-a22(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), {I,Ni}pk(R) ); + recv_!2( R, I, Ci, Cr, algo, Gr, {R,Nr}pk(I), HASH_Ri ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, {HASH_Ii}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, {I,Ni}pk(R) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, g(r), {R,Nr}pk(I), HASH_Rr ); + recv_!3( I, R, Ci, Cr, {HASH_Ir}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a22.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a22.spdl new file mode 100644 index 0000000..1c59323 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-a22.spdl @@ -0,0 +1,128 @@ +# 1 "ikev1-pk-a22.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk-a22.cpp" +# 17 "ikev1-pk-a22.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-pk-a22.cpp" 2 +# 27 "ikev1-pk-a22.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R) ); + send_!O2( O, O, prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R) ); + + + recv_!O3( O, O, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O4( O, O, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} + +protocol ikev1-pk-a22(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), {I,Ni}pk(R) ); + recv_!2( R, I, Ci, Cr, algo, Gr, {R,Nr}pk(I), prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, {I,Ni}pk(R) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, g(r), {R,Nr}pk(I), prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R) ); + recv_!3( I, R, Ci, Cr, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m.cpp new file mode 100644 index 0000000..1b27c5f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m.cpp @@ -0,0 +1,103 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Public key authentication (main mode) + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define HASH1 H({R, pk(R)}sk(s)) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 5 + recv_!O1( O, O, {HASH_Ii}SKi ); + send_!O2( O, O, {HASH_Ir}SKr ); + + // msg 6 + recv_!O3( O, O, {HASH_Rr}SKr ); + send_!O4( O, O, {HASH_Ri}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-pk-m(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), {I}pk(R), {Ni}pk(R) ); + recv_4( R, I, Ci, Cr, Gr, {R}pk(I), {Nr}pk(I) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!5( I, R, Ci, Cr, {HASH_Ii}SKi ); + recv_!6( R, I, Ci, Cr, {HASH_Ri}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, {I}pk(R), {Ni}pk(R) ); + send_4( R, I, Ci, Cr, g(r), {R}pk(I), {Nr}pk(I) ); + recv_!5( I, R, Ci, Cr, {HASH_Ir}SKr ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!6( R, I, Ci, Cr, {HASH_Rr}SKr ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m.spdl new file mode 100644 index 0000000..8436133 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m.spdl @@ -0,0 +1,136 @@ +# 1 "ikev1-pk-m.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk-m.cpp" +# 16 "ikev1-pk-m.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 17 "ikev1-pk-m.cpp" 2 +# 27 "ikev1-pk-m.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O2( O, O, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + + recv_!O3( O, O, {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + send_!O4( O, O, {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + + } + + +} + + +protocol ikev1-pk-m(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), {I}pk(R), {Ni}pk(R) ); + recv_4( R, I, Ci, Cr, Gr, {R}pk(I), {Nr}pk(I) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!5( I, R, Ci, Cr, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + recv_!6( R, I, Ci, Cr, {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, {I}pk(R), {Ni}pk(R) ); + send_4( R, I, Ci, Cr, g(r), {R}pk(I), {Nr}pk(I) ); + recv_!5( I, R, Ci, Cr, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!6( R, I, Ci, Cr, {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m2.cpp new file mode 100644 index 0000000..fc08ea0 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m2.cpp @@ -0,0 +1,102 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Public key authentication (main mode), + * Nonce and id encrypted together + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 5 + recv_!O1( O, O, {HASH_Ii}SKi ); + send_!O2( O, O, {HASH_Ir}SKr ); + + // msg 6 + recv_!O3( O, O, {HASH_Rr}SKr ); + send_!O4( O, O, {HASH_Ri}SKi ); + + } +#undef Gi +#undef Gr +} + +protocol ikev1-pk-m2(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), {I,Ni}pk(R) ); + recv_4( R, I, Ci, Cr, Gr, {R,Nr}pk(I) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!5( I, R, Ci, Cr, {HASH_Ii}SKi ); + recv_!6( R, I, Ci, Cr, {HASH_Ri}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, {I,Ni}pk(R) ); + send_4( R, I, Ci, Cr, g(r), {R,Nr}pk(I) ); + recv_!5( I, R, Ci, Cr, {HASH_Ir}SKr ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!6( R, I, Ci, Cr, {HASH_Rr}SKr ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m2.spdl new file mode 100644 index 0000000..b625de5 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk-m2.spdl @@ -0,0 +1,135 @@ +# 1 "ikev1-pk-m2.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk-m2.cpp" +# 17 "ikev1-pk-m2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-pk-m2.cpp" 2 +# 27 "ikev1-pk-m2.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O2( O, O, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + + recv_!O3( O, O, {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + send_!O4( O, O, {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + + } + + +} + +protocol ikev1-pk-m2(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), {I,Ni}pk(R) ); + recv_4( R, I, Ci, Cr, Gr, {R,Nr}pk(I) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!5( I, R, Ci, Cr, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + recv_!6( R, I, Ci, Cr, {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, {I,Ni}pk(R) ); + send_4( R, I, Ci, Cr, g(r), {R,Nr}pk(I) ); + recv_!5( I, R, Ci, Cr, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!6( R, I, Ci, Cr, {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a.cpp new file mode 100644 index 0000000..9549e44 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a.cpp @@ -0,0 +1,97 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Revised public key authentication (aggressive mode) + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define Nei prf(Ni, Ci) +#define Ner prf(Nr, Cr) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, HASH_Rr ); + send_!O2( O, O, HASH_Ri ); + + // msg 3 + recv_!O3( O, O, HASH_Ir ); + send_!O4( O, O, HASH_Ii ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-pk2-a(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, {Ni}pk(R), {g(i)}Nei, {I}Nei ); + recv_!2( R, I, Ci, Cr, algo, {Nr}pk(I), {Gr}Ner, {R}Ner, HASH_Ri ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, HASH_Ii ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, {Ni}pk(R), {Gi}Nei, {I}Nei ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, {Nr}pk(I), {g(r)}Ner, {R}Ner, HASH_Rr ); + recv_!3( I, R, Ci, Cr, HASH_Ir ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a.spdl new file mode 100644 index 0000000..971122a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a.spdl @@ -0,0 +1,129 @@ +# 1 "ikev1-pk2-a.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk2-a.cpp" +# 16 "ikev1-pk2-a.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 17 "ikev1-pk2-a.cpp" 2 +# 28 "ikev1-pk2-a.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R) ); + send_!O2( O, O, prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R) ); + + + recv_!O3( O, O, prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I) ); + send_!O4( O, O, prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I) ); + + } + + +} + + +protocol ikev1-pk2-a(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, {Ni}pk(R), {g(i)}prf(Ni, Ci), {I}prf(Ni, Ci) ); + recv_!2( R, I, Ci, Cr, algo, {Nr}pk(I), {Gr}prf(Nr, Cr), {R}prf(Nr, Cr), prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, {Ni}pk(R), {Gi}prf(Ni, Ci), {I}prf(Ni, Ci) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, {Nr}pk(I), {g(r)}prf(Nr, Cr), {R}prf(Nr, Cr), prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R) ); + recv_!3( I, R, Ci, Cr, prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a2.cpp new file mode 100644 index 0000000..a8536fb --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a2.cpp @@ -0,0 +1,97 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Revised public key authentication (aggressive mode), + * Diffie-Hellman token encrypted together with identity + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define Nei prf(Ni, Ci) +#define Ner prf(Nr, Cr) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, HASH_Rr ); + send_!O2( O, O, HASH_Ri ); + + // msg 3 + recv_!O3( O, O, HASH_Ir ); + send_!O4( O, O, HASH_Ii ); + + } +#undef Gi +#undef Gr +} + +protocol ikev1-pk2-a2(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, {Ni}pk(R), {g(i),I}Nei ); + recv_!2( R, I, Ci, Cr, algo, {Nr}pk(I), {Gr,R}Ner, HASH_Ri ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, HASH_Ii ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, {Ni}pk(R), {Gi,I}Nei ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, {Nr}pk(I), {g(r),R}Ner, HASH_Rr ); + recv_!3( I, R, Ci, Cr, HASH_Ir ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a2.spdl new file mode 100644 index 0000000..51e0d17 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-a2.spdl @@ -0,0 +1,128 @@ +# 1 "ikev1-pk2-a2.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk2-a2.cpp" +# 17 "ikev1-pk2-a2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-pk2-a2.cpp" 2 +# 29 "ikev1-pk2-a2.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R) ); + send_!O2( O, O, prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R) ); + + + recv_!O3( O, O, prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I) ); + send_!O4( O, O, prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I) ); + + } + + +} + +protocol ikev1-pk2-a2(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, {Ni}pk(R), {g(i),I}prf(Ni, Ci) ); + recv_!2( R, I, Ci, Cr, algo, {Nr}pk(I), {Gr,R}prf(Nr, Cr), prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!3( I, R, Ci, Cr, prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, {Ni}pk(R), {Gi,I}prf(Ni, Ci) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!2( R, I, Ci, Cr, algo, {Nr}pk(I), {g(r),R}prf(Nr, Cr), prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R) ); + recv_!3( I, R, Ci, Cr, prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m.cpp new file mode 100644 index 0000000..42f2d9d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m.cpp @@ -0,0 +1,104 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Revised public key authentication (main mode) + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define Nei prf(Ni, Ci) +#define Ner prf(Nr, Cr) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 5 + recv_!O1( O, O, {HASH_Ii}SKi ); + send_!O2( O, O, {HASH_Ir}SKr ); + + // msg 6 + recv_!O3( O, O, {HASH_Rr}SKr ); + send_!O4( O, O, {HASH_Ri}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-pk2-m(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, {Ni}pk(R), {g(i)}Nei, {I}Nei ); + recv_4( R, I, Ci, Cr, {Nr}pk(I), {Gr}Ner, {R}Ner ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!5( I, R, Ci, Cr, {HASH_Ii}SKi ); + recv_!6( R, I, Ci, Cr, {HASH_Ri}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, {Ni}pk(R), {Gi}Nei, {I}Nei ); + send_4( R, I, Ci, Cr, {Nr}pk(I), {g(r)}Ner, {R}Ner ); + recv_!5( I, R, Ci, Cr, {HASH_Ir}SKr ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!6( R, I, Ci, Cr, {HASH_Rr}SKr ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m.spdl new file mode 100644 index 0000000..e32dd5b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m.spdl @@ -0,0 +1,136 @@ +# 1 "ikev1-pk2-m.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk2-m.cpp" +# 16 "ikev1-pk2-m.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 17 "ikev1-pk2-m.cpp" 2 +# 28 "ikev1-pk2-m.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O2( O, O, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + + recv_!O3( O, O, {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + send_!O4( O, O, {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + + } + + +} + + +protocol ikev1-pk2-m(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, {Ni}pk(R), {g(i)}prf(Ni, Ci), {I}prf(Ni, Ci) ); + recv_4( R, I, Ci, Cr, {Nr}pk(I), {Gr}prf(Nr, Cr), {R}prf(Nr, Cr) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!5( I, R, Ci, Cr, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + recv_!6( R, I, Ci, Cr, {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, {Ni}pk(R), {Gi}prf(Ni, Ci), {I}prf(Ni, Ci) ); + send_4( R, I, Ci, Cr, {Nr}pk(I), {g(r)}prf(Nr, Cr), {R}prf(Nr, Cr) ); + recv_!5( I, R, Ci, Cr, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!6( R, I, Ci, Cr, {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m2.cpp new file mode 100644 index 0000000..653a839 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m2.cpp @@ -0,0 +1,106 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Revised public key authentication (aggressive mode), + * Diffie-Hellman token encrypted together with identity + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(H(Ni,Nr),Ci,Cr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) +#define HASH1 H({R, pk(R)}sk(s)) +#define Nei prf(Ni, Ci) +#define Ner prf(Nr, Cr) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 5 + recv_!O1( O, O, {HASH_Ii}SKi ); + send_!O2( O, O, {HASH_Ir}SKr ); + + // msg 6 + recv_!O3( O, O, {HASH_Rr}SKr ); + send_!O4( O, O, {HASH_Ri}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-pk2-m2(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, {Ni}pk(R), {g(i),I}Nei ); + recv_4( R, I, Ci, Cr, {Nr}pk(I), {Gr,R}Ner ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!5( I, R, Ci, Cr, {HASH_Ii}SKi ); + recv_!6( R, I, Ci, Cr, {HASH_Ri}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, {Ni}pk(R), {Gi,I}Nei ); + send_4( R, I, Ci, Cr, {Nr}pk(I), {g(r),R}Ner ); + recv_!5( I, R, Ci, Cr, {HASH_Ir}SKr ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!6( R, I, Ci, Cr, {HASH_Rr}SKr ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m2.spdl new file mode 100644 index 0000000..62e5b74 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-pk2-m2.spdl @@ -0,0 +1,136 @@ +# 1 "ikev1-pk2-m2.cpp" +# 1 "<command-line>" +# 1 "ikev1-pk2-m2.cpp" +# 17 "ikev1-pk2-m2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-pk2-m2.cpp" 2 +# 30 "ikev1-pk2-m2.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O2( O, O, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + + recv_!O3( O, O, {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + send_!O4( O, O, {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + + } + + +} + + +protocol ikev1-pk2-m2(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, {Ni}pk(R), {g(i),I}prf(Ni, Ci) ); + recv_4( R, I, Ci, Cr, {Nr}pk(I), {Gr,R}prf(Nr, Cr) ); + claim( I, Running, R, g(i),Gr,Ci,Cr,Ni,Nr ); + send_!5( I, R, Ci, Cr, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + recv_!6( R, I, Ci, Cr, {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, g(i),Gr,Ci,Cr,Ni,Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, {Ni}pk(R), {Gi,I}prf(Ni, Ci) ); + send_4( R, I, Ci, Cr, {Nr}pk(I), {g(r),R}prf(Nr, Cr) ); + recv_!5( I, R, Ci, Cr, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + claim( R, Running, I, Gi,g(r),Ci,Cr,Ni,Nr ); + send_!6( R, I, Ci, Cr, {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Gi,g(r),Ci,Cr,Ni,Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-a.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-a.cpp new file mode 100644 index 0000000..bdd5b4c --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-a.cpp @@ -0,0 +1,94 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Pre-shared key authentication (aggressive mode) + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1_PSK__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define HASH_Ii prf(k(I,R), Ni, Nr, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(k(R,I), Ni, Nr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(k(I,R), Ni, Nr, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(k(R,I), Ni, Nr, g(r), Gi, Cr, Ci, list, R) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, HASH_Rr ); + send_!O2( O, O, HASH_Ri ); + + // msg 3 + recv_!O3( O, O, HASH_Ii ); + send_!O4( O, O, HASH_Ir ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-psk-a(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni, I ); + recv_!2( R, I, Ci, Cr, algo, Gr, Nr, R, HASH_Ri ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, Ci, Cr, HASH_Ii ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni, I ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, Ci, Cr, algo, g(r), Nr, R, HASH_Rr ); + recv_!3( I, R, Ci, Cr, HASH_Ir ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-a.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-a.spdl new file mode 100644 index 0000000..788dde0 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-a.spdl @@ -0,0 +1,125 @@ +# 1 "ikev1-psk-a.cpp" +# 1 "<command-line>" +# 1 "ikev1-psk-a.cpp" +# 16 "ikev1-psk-a.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + + + + var Ci, Cr: Nonce; + var I, R: Agent; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, prf(k(I,R), Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, prf(k(R,I), Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 17 "ikev1-psk-a.cpp" 2 +# 25 "ikev1-psk-a.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(k(R,I), Ni, Nr, g(r), g(i), Cr, Ci, list, R) ); + send_!O2( O, O, prf(k(I,R), Ni, Nr, g(r), g(i), Cr, Ci, list, R) ); + + + recv_!O3( O, O, prf(k(I,R), Ni, Nr, g(i), g(r), Ci, Cr, list, I) ); + send_!O4( O, O, prf(k(R,I), Ni, Nr, g(i), g(r), Ci, Cr, list, I) ); + + } + + +} + + +protocol ikev1-psk-a(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni, I ); + recv_!2( R, I, Ci, Cr, algo, Gr, Nr, R, prf(k(I,R), Ni, Nr, Gr, g(i), Cr, Ci, list, R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, Ci, Cr, prf(k(I,R), Ni, Nr, g(i), Gr, Ci, Cr, list, I) ); + + + claim( I, SKR, prf(k(I,R), Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni, I ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, Ci, Cr, algo, g(r), Nr, R, prf(k(R,I), Ni, Nr, g(r), Gi, Cr, Ci, list, R) ); + recv_!3( I, R, Ci, Cr, prf(k(R,I), Ni, Nr, Gi, g(r), Ci, Cr, list, I) ); + + + claim( R, SKR, prf(k(R,I), Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m-perlman.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m-perlman.cpp new file mode 100644 index 0000000..01640ad --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m-perlman.cpp @@ -0,0 +1,101 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Pre-shared key authentication (main mode) incorporating + * a fix by Perlman et. al. + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1_PSK__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define HASH_Ii prf(k(I,R), Ni, Nr, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(k(R,I), Ni, Nr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(k(I,R), Ni, Nr, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(k(R,I), Ni, Nr, g(r), Gi, Cr, Ci, list, R) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 5 + recv_!O1( O, O, {I, HASH_Ii}Zi ); + send_!O2( O, O, {I, HASH_Ir}Zr ); + + // msg 6 + recv_!O3( O, O, {R, HASH_Rr}Zr ); + send_!O4( O, O, {R, HASH_Ri}Zi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-psk-m-perlman(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), Ni ); + recv_4( R, I, Ci, Cr, Gr, Nr ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!5( I, R, Ci, Cr, {I, HASH_Ii}Zi ); + recv_!6( R, I, Ci, Cr, {R, HASH_Ri}Zi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, Ni ); + send_4( R, I, Ci, Cr, g(r), Nr ); + recv_!5( I, R, Ci, Cr, {I, HASH_Ir}Zr ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!6( R, I, Ci, Cr, {R, HASH_Rr}Zr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m-perlman.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m-perlman.spdl new file mode 100644 index 0000000..fa9436a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m-perlman.spdl @@ -0,0 +1,131 @@ +# 1 "ikev1-psk-m-perlman.cpp" +# 1 "<command-line>" +# 1 "ikev1-psk-m-perlman.cpp" +# 17 "ikev1-psk-m-perlman.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + + + + var Ci, Cr: Nonce; + var I, R: Agent; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, prf(k(I,R), Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, prf(k(R,I), Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-psk-m-perlman.cpp" 2 +# 26 "ikev1-psk-m-perlman.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {I, prf(k(I,R), Ni, Nr, g(i), g(r), Ci, Cr, list, I)}h(g(r),i) ); + send_!O2( O, O, {I, prf(k(R,I), Ni, Nr, g(i), g(r), Ci, Cr, list, I)}h(g(i),r) ); + + + recv_!O3( O, O, {R, prf(k(R,I), Ni, Nr, g(r), g(i), Cr, Ci, list, R)}h(g(i),r) ); + send_!O4( O, O, {R, prf(k(I,R), Ni, Nr, g(r), g(i), Cr, Ci, list, R)}h(g(r),i) ); + + } + + +} + + +protocol ikev1-psk-m-perlman(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), Ni ); + recv_4( R, I, Ci, Cr, Gr, Nr ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!5( I, R, Ci, Cr, {I, prf(k(I,R), Ni, Nr, g(i), Gr, Ci, Cr, list, I)}h(Gr,i) ); + recv_!6( R, I, Ci, Cr, {R, prf(k(I,R), Ni, Nr, Gr, g(i), Cr, Ci, list, R)}h(Gr,i) ); + + + claim( I, SKR, prf(k(I,R), Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, Ni ); + send_4( R, I, Ci, Cr, g(r), Nr ); + recv_!5( I, R, Ci, Cr, {I, prf(k(R,I), Ni, Nr, Gi, g(r), Ci, Cr, list, I)}h(Gi,r) ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!6( R, I, Ci, Cr, {R, prf(k(R,I), Ni, Nr, g(r), Gi, Cr, Ci, list, R)}h(Gi,r) ); + + + claim( R, SKR, prf(k(R,I), Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m.cpp new file mode 100644 index 0000000..f203018 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m.cpp @@ -0,0 +1,100 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Pre-shared key authentication (main mode) + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1_PSK__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYID prf(k(I,R),Ni,Nr) +#define HASH_Ii prf(k(I,R), Ni, Nr, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(k(R,I), Ni, Nr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(k(I,R), Ni, Nr, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(k(R,I), Ni, Nr, g(r), Gi, Cr, Ci, list, R) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 5 + recv_!O1( O, O, {I, HASH_Ii}SKi ); + send_!O2( O, O, {I, HASH_Ir}SKr ); + + // msg 6 + recv_!O3( O, O, {R, HASH_Rr}SKr ); + send_!O4( O, O, {R, HASH_Ri}SKi ); + + } +#undef Gi +#undef Gr +} + +protocol ikev1-psk-m(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), Ni ); + recv_4( R, I, Ci, Cr, Gr, Nr ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!5( I, R, Ci, Cr, {I, HASH_Ii}SKi ); + recv_!6( R, I, Ci, Cr, {R, HASH_Ri}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, Ni ); + send_4( R, I, Ci, Cr, g(r), Nr ); + recv_!5( I, R, Ci, Cr, {I, HASH_Ir}SKr ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!6( R, I, Ci, Cr, {R, HASH_Rr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m.spdl new file mode 100644 index 0000000..ca7a688 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-psk-m.spdl @@ -0,0 +1,130 @@ +# 1 "ikev1-psk-m.cpp" +# 1 "<command-line>" +# 1 "ikev1-psk-m.cpp" +# 16 "ikev1-psk-m.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + + + + var Ci, Cr: Nonce; + var I, R: Agent; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, prf(k(I,R), Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, prf(k(R,I), Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 17 "ikev1-psk-m.cpp" 2 +# 26 "ikev1-psk-m.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {I, prf(k(I,R), Ni, Nr, g(i), g(r), Ci, Cr, list, I)}prf(k(I,R), Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O2( O, O, {I, prf(k(R,I), Ni, Nr, g(i), g(r), Ci, Cr, list, I)}prf(k(R,I), Ni, Nr, h(g(i),r), Ci, Cr) ); + + + recv_!O3( O, O, {R, prf(k(R,I), Ni, Nr, g(r), g(i), Cr, Ci, list, R)}prf(k(R,I), Ni, Nr, h(g(i),r), Ci, Cr) ); + send_!O4( O, O, {R, prf(k(I,R), Ni, Nr, g(r), g(i), Cr, Ci, list, R)}prf(k(I,R), Ni, Nr, h(g(r),i), Ci, Cr) ); + + } + + +} + +protocol ikev1-psk-m(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), Ni ); + recv_4( R, I, Ci, Cr, Gr, Nr ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!5( I, R, Ci, Cr, {I, prf(k(I,R), Ni, Nr, g(i), Gr, Ci, Cr, list, I)}prf(k(I,R), Ni, Nr, h(Gr,i), Ci, Cr) ); + recv_!6( R, I, Ci, Cr, {R, prf(k(I,R), Ni, Nr, Gr, g(i), Cr, Ci, list, R)}prf(k(I,R), Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, prf(k(I,R), Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, Ni ); + send_4( R, I, Ci, Cr, g(r), Nr ); + recv_!5( I, R, Ci, Cr, {I, prf(k(R,I), Ni, Nr, Gi, g(r), Ci, Cr, list, I)}prf(k(R,I), Ni, Nr, h(Gi,r), Ci, Cr) ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!6( R, I, Ci, Cr, {R, prf(k(R,I), Ni, Nr, g(r), Gi, Cr, Ci, list, R)}prf(k(R,I), Ni, Nr, h(Gi,r), Ci, Cr) ); + + + claim( R, SKR, prf(k(R,I), Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-noid.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-noid.cpp new file mode 100644 index 0000000..f6f5712 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-noid.cpp @@ -0,0 +1,102 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Quick mode (pfs), without optional identities + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1_QUICK__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/* k(I,R)=k(R,I) equal Ka from the spec */ +#define HASH1i prf(k(I,R), mid, list, Ni, g(i)) +#define HASH1r prf(k(R,I), mid, list, Ni, Gi) +#define HASH2i prf(k(I,R), mid, Ni, algo, Nr, Gr) +#define HASH2r prf(k(R,I), mid, Ni, algo, Nr, g(r)) +#define HASH3i prf(k(I,R), mid, Ni, Nr) +#define HASH3r prf(k(R,I), mid, Ni, Nr) + +usertype String; +const list, algo: String; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling k(I,R) = k(R,I). + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var mid, i, r, Ni, Nr: Nonce; + var I, R: Agent; + + // msg 1 + recv_!O1( O, O, {HASH1i, list, Ni, g(i)}k(I,R) ); + send_!O2( O, O, {HASH1r, list, Ni, Gi}k(R,I) ); + + // msg 2 + recv_!O3( O, O, {HASH2r, algo, Nr, g(r)}k(R,I) ); + send_!O4( O, O, {HASH2i, algo, Nr, Gr}k(I,R) ); + + // msg 3 + recv_!O5( O, O, {HASH3i}k(I,R) ); + send_!O6( O, O, {HASH3r}k(R,I) ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-quick-noid(I, R) +{ + role I { + fresh i, Ni, Ci, mid: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_!1( I, R, mid, {HASH1i, list, Ni, g(i)}k(I,R) ); + recv_!2( R, I, mid, {HASH2i, algo, Nr, Gr}k(I,R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr ); + send_!3( I, R, mid, {HASH3i}k(I,R) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci, mid: Nonce; + var Gi: Ticket; + + recv_!1( I, R, mid, {HASH1r, list, Ni, Gi}k(R,I) ); + claim( R, Running, I, Ni, Nr, Gi, g(r) ); + send_!2( R, I, mid, {HASH2r, algo, Nr, g(r)}k(R,I) ); + recv_!3( I, R, mid, {HASH3r}k(R,I) ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r) ); + + } +} +// TODO: Incorporate into various phase 1 protocols (see spec for adaptions) +// NOTE: If incorporated in phase 1, make sure to model with and without optional identities in msg 2 & 3 diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-noid.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-noid.spdl new file mode 100644 index 0000000..03e9c05 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-noid.spdl @@ -0,0 +1,124 @@ +# 1 "ikev1-quick-noid.cpp" +# 1 "<command-line>" +# 1 "ikev1-quick-noid.cpp" +# 16 "ikev1-quick-noid.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 126 "common.h" + var I, R: Agent; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(k(I,R),h(g(r),i),Ni,Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(k(R,I),h(g(i),r),Ni,Nr) ); + + } + + +} +# 17 "ikev1-quick-noid.cpp" 2 +# 27 "ikev1-quick-noid.cpp" +usertype String; +const list, algo: String; + + + + + + +protocol @executability(O) { + + + role O { + var mid, i, r, Ni, Nr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {prf(k(I,R), mid, list, Ni, g(i)), list, Ni, g(i)}k(I,R) ); + send_!O2( O, O, {prf(k(R,I), mid, list, Ni, g(i)), list, Ni, g(i)}k(R,I) ); + + + recv_!O3( O, O, {prf(k(R,I), mid, Ni, algo, Nr, g(r)), algo, Nr, g(r)}k(R,I) ); + send_!O4( O, O, {prf(k(I,R), mid, Ni, algo, Nr, g(r)), algo, Nr, g(r)}k(I,R) ); + + + recv_!O5( O, O, {prf(k(I,R), mid, Ni, Nr)}k(I,R) ); + send_!O6( O, O, {prf(k(R,I), mid, Ni, Nr)}k(R,I) ); + + } + + +} + + +protocol ikev1-quick-noid(I, R) +{ + role I { + fresh i, Ni, Ci, mid: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_!1( I, R, mid, {prf(k(I,R), mid, list, Ni, g(i)), list, Ni, g(i)}k(I,R) ); + recv_!2( R, I, mid, {prf(k(I,R), mid, Ni, algo, Nr, Gr), algo, Nr, Gr}k(I,R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr ); + send_!3( I, R, mid, {prf(k(I,R), mid, Ni, Nr)}k(I,R) ); + + + claim( I, SKR, KDF(k(I,R),h(Gr,i),Ni,Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci, mid: Nonce; + var Gi: Ticket; + + recv_!1( I, R, mid, {prf(k(R,I), mid, list, Ni, Gi), list, Ni, Gi}k(R,I) ); + claim( R, Running, I, Ni, Nr, Gi, g(r) ); + send_!2( R, I, mid, {prf(k(R,I), mid, Ni, algo, Nr, g(r)), algo, Nr, g(r)}k(R,I) ); + recv_!3( I, R, mid, {prf(k(R,I), mid, Ni, Nr)}k(R,I) ); + + + + claim( R, SKR, KDF(k(R,I),h(Gi,r),Ni,Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r) ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-nopfs.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-nopfs.cpp new file mode 100644 index 0000000..38a1fc4 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-nopfs.cpp @@ -0,0 +1,96 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Quick mode (no pfs), without optional identities + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1_QUICK_NOPFS__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/* k(I,R)=k(R,I) equal Ka from the spec */ +#define HASH1i prf(k(I,R), mid, list, Ni) +#define HASH1r prf(k(R,I), mid, list, Ni) +#define HASH2i prf(k(I,R), mid, Ni, algo, Nr) +#define HASH2r prf(k(R,I), mid, Ni, algo, Nr) +#define HASH3i prf(k(I,R), mid, Ni, Nr) +#define HASH3r prf(k(R,I), mid, Ni, Nr) + +usertype String; +const list, algo: String; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling k(I,R) = k(R,I). + */ +protocol @executability(O) { + role O { + var mid, Ni, Nr: Nonce; + var I, R: Agent; + + // msg 1 + recv_!O1( O, O, {HASH1i, list, Ni}k(I,R) ); + send_!O2( O, O, {HASH1r, list, Ni}k(R,I) ); + + // msg 2 + recv_!O3( O, O, {HASH2r, algo, Nr}k(R,I) ); + send_!O4( O, O, {HASH2i, algo, Nr}k(I,R) ); + + // msg 3 + recv_!O5( O, O, {HASH3i}k(I,R) ); + send_!O6( O, O, {HASH3r}k(R,I) ); + + } +} + + +protocol ikev1-quick-nopfs(I, R) +{ + role I { + fresh i, Ni, Ci, mid: Nonce; + var Nr, Cr: Nonce; + + send_!1( I, R, mid, {HASH1i, list, Ni}k(I,R) ); + recv_!2( R, I, mid, {HASH2i, algo, Nr}k(I,R) ); + claim( I, Running, R, Ni, Nr ); + send_!3( I, R, mid, {HASH3i}k(I,R) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci, mid: Nonce; + + recv_!1( I, R, mid, {HASH1r, list, Ni}k(R,I) ); + claim( R, Running, I, Ni, Nr ); + send_!2( R, I, mid, {HASH2r, algo, Nr}k(R,I) ); + recv_!3( I, R, mid, {HASH3r}k(R,I) ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr ); + + } +} +// TODO: Incorporate into various phase 1 protocols (see spec for adaptions) +// NOTE: If incorporated in phase 1, make sure to model with and without optional identities in msg 2 & 3 diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-nopfs.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-nopfs.spdl new file mode 100644 index 0000000..c7d2f99 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick-nopfs.spdl @@ -0,0 +1,118 @@ +# 1 "ikev1-quick-nopfs.cpp" +# 1 "<command-line>" +# 1 "ikev1-quick-nopfs.cpp" +# 16 "ikev1-quick-nopfs.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 129 "common.h" + var I, R: Agent; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(k(I,R),Ni,Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(k(R,I),Ni,Nr) ); + + } + + +} +# 17 "ikev1-quick-nopfs.cpp" 2 +# 27 "ikev1-quick-nopfs.cpp" +usertype String; +const list, algo: String; + + + + + + +protocol @executability(O) { + role O { + var mid, Ni, Nr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {prf(k(I,R), mid, list, Ni), list, Ni}k(I,R) ); + send_!O2( O, O, {prf(k(R,I), mid, list, Ni), list, Ni}k(R,I) ); + + + recv_!O3( O, O, {prf(k(R,I), mid, Ni, algo, Nr), algo, Nr}k(R,I) ); + send_!O4( O, O, {prf(k(I,R), mid, Ni, algo, Nr), algo, Nr}k(I,R) ); + + + recv_!O5( O, O, {prf(k(I,R), mid, Ni, Nr)}k(I,R) ); + send_!O6( O, O, {prf(k(R,I), mid, Ni, Nr)}k(R,I) ); + + } +} + + +protocol ikev1-quick-nopfs(I, R) +{ + role I { + fresh i, Ni, Ci, mid: Nonce; + var Nr, Cr: Nonce; + + send_!1( I, R, mid, {prf(k(I,R), mid, list, Ni), list, Ni}k(I,R) ); + recv_!2( R, I, mid, {prf(k(I,R), mid, Ni, algo, Nr), algo, Nr}k(I,R) ); + claim( I, Running, R, Ni, Nr ); + send_!3( I, R, mid, {prf(k(I,R), mid, Ni, Nr)}k(I,R) ); + + + claim( I, SKR, KDF(k(I,R),Ni,Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci, mid: Nonce; + + recv_!1( I, R, mid, {prf(k(R,I), mid, list, Ni), list, Ni}k(R,I) ); + claim( R, Running, I, Ni, Nr ); + send_!2( R, I, mid, {prf(k(R,I), mid, Ni, algo, Nr), algo, Nr}k(R,I) ); + recv_!3( I, R, mid, {prf(k(R,I), mid, Ni, Nr)}k(R,I) ); + + + + claim( R, SKR, KDF(k(R,I),Ni,Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick.cpp new file mode 100644 index 0000000..60e9fcc --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick.cpp @@ -0,0 +1,70 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Quick mode (pfs), optional identities included + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1_QUICK__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/* k(I,R) equals Ka from the spec */ +#define HASH1i prf(k(I,R), mid, list, Ni, g(i), I, R) +#define HASH1r prf(k(R,I), mid, list, Ni, Gi, I, R) +#define HASH2i prf(k(I,R), mid, Ni, algo, Nr, Gr, I, R) +#define HASH2r prf(k(R,I), mid, Ni, algo, Nr, g(r), I, R) +#define HASH3i prf(k(I,R), mid, Ni, Nr) +#define HASH3r prf(k(R,I), mid, Ni, Nr) + + +protocol ikev1-quick(I, R) +{ + role I { + fresh i, Ni, Ci, mid, list: Nonce; + var Nr, Cr, algo: Nonce; + var Gr: Ticket; + + send_!1( I, R, mid, {HASH1i, list, Ni, g(i), I, R}k(I,R) ); + recv_!2( R, I, mid, {HASH2i, algo, Nr, Gr, I, R}k(I,R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr ); + send_!3( I, R, mid, {HASH3i}k(I,R) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr ); + + } + + role R { + fresh r, Nr, Cr, algo: Nonce; + var Ni, Ci, mid, list: Nonce; + var Gi: Ticket; + + recv_!1( I, R, mid, {HASH1r, list, Ni, Gi, I, R}k(I,R) ); + claim( R, Running, I, Ni, Nr, Gi, g(r) ); + send_!2( R, I, mid, {HASH2r, algo, Nr, g(r), I, R}k(I,R) ); + recv_!3( I, R, mid, {HASH3r}k(I,R) ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r) ); + + } +} +// TODO: Incorporate into various phase 1 protocols (see spec for adaptions) +// NOTE: If incorporated in phase 1, make sure to model with and without optional identities in msg 2 & 3 diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick.spdl new file mode 100644 index 0000000..6a723c7 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-quick.spdl @@ -0,0 +1,91 @@ +# 1 "ikev1-quick.cpp" +# 1 "<command-line>" +# 1 "ikev1-quick.cpp" +# 16 "ikev1-quick.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 126 "common.h" + var I, R: Agent; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(k(I,R),h(g(r),i),Ni,Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(k(R,I),h(g(i),r),Ni,Nr) ); + + } + + +} +# 17 "ikev1-quick.cpp" 2 +# 28 "ikev1-quick.cpp" +protocol ikev1-quick(I, R) +{ + role I { + fresh i, Ni, Ci, mid, list: Nonce; + var Nr, Cr, algo: Nonce; + var Gr: Ticket; + + send_!1( I, R, mid, {prf(k(I,R), mid, list, Ni, g(i), I, R), list, Ni, g(i), I, R}k(I,R) ); + recv_!2( R, I, mid, {prf(k(I,R), mid, Ni, algo, Nr, Gr, I, R), algo, Nr, Gr, I, R}k(I,R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr ); + send_!3( I, R, mid, {prf(k(I,R), mid, Ni, Nr)}k(I,R) ); + + + claim( I, SKR, KDF(k(I,R),h(Gr,i),Ni,Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr ); + + } + + role R { + fresh r, Nr, Cr, algo: Nonce; + var Ni, Ci, mid, list: Nonce; + var Gi: Ticket; + + recv_!1( I, R, mid, {prf(k(R,I), mid, list, Ni, Gi, I, R), list, Ni, Gi, I, R}k(I,R) ); + claim( R, Running, I, Ni, Nr, Gi, g(r) ); + send_!2( R, I, mid, {prf(k(R,I), mid, Ni, algo, Nr, g(r), I, R), algo, Nr, g(r), I, R}k(I,R) ); + recv_!3( I, R, mid, {prf(k(R,I), mid, Ni, Nr)}k(I,R) ); + + + + claim( R, SKR, KDF(k(R,I),h(Gi,r),Ni,Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r) ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman1.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman1.cpp new file mode 100644 index 0000000..ddebfcb --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman1.cpp @@ -0,0 +1,99 @@ +/*********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Digital signature authentication (aggressive mode) with + * a modification suggested by Perlman et al. (last msg not + * encrypted) + ***********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define HDR (Ci,Cr) +#define SKEYIDi prf(Ni,Nr,Zi) +#define SKEYIDr prf(Ni,Nr,Zr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, {R}SKr, {HASH_Rr}sk(R) ); + send_!O2( O, O, {R}SKi, {HASH_Ri}sk(R) ); + + // msg 3 + recv_!O3( O, O, {I}SKi, {HASH_Ii}sk(I) ); + send_!O4( O, O, {I}SKr, {HASH_Ir}sk(I) ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-sig-a-perlman1(I, R) +{ + + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni ); + recv_!2( R, I, HDR, algo, Gr, Nr, {R}SKi, {HASH_Ri}sk(R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, HDR, {I}SKi, {HASH_Ii}sk(I) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, HDR, algo, g(r), Nr, R, {R}SKr, {HASH_Rr}sk(R) ); + recv_!3( I, R, HDR, {I}SKr, {HASH_Ir}sk(I) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman1.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman1.spdl new file mode 100644 index 0000000..f758a99 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman1.spdl @@ -0,0 +1,130 @@ +# 1 "ikev1-sig-a-perlman1.cpp" +# 1 "<command-line>" +# 1 "ikev1-sig-a-perlman1.cpp" +# 18 "ikev1-sig-a-perlman1.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 19 "ikev1-sig-a-perlman1.cpp" 2 +# 29 "ikev1-sig-a-perlman1.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {R}KDF(Ni, Nr, h(g(i),r), Ci, Cr), {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}sk(R) ); + send_!O2( O, O, {R}KDF(Ni, Nr, h(g(r),i), Ci, Cr), {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}sk(R) ); + + + recv_!O3( O, O, {I}KDF(Ni, Nr, h(g(r),i), Ci, Cr), {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}sk(I) ); + send_!O4( O, O, {I}KDF(Ni, Nr, h(g(i),r), Ci, Cr), {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}sk(I) ); + + } + + +} + + +protocol ikev1-sig-a-perlman1(I, R) +{ + + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni ); + recv_!2( R, I, (Ci,Cr), algo, Gr, Nr, {R}KDF(Ni, Nr, h(Gr,i), Ci, Cr), {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}sk(R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, (Ci,Cr), {I}KDF(Ni, Nr, h(Gr,i), Ci, Cr), {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}sk(I) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, (Ci,Cr), algo, g(r), Nr, R, {R}KDF(Ni, Nr, h(Gi,r), Ci, Cr), {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}sk(R) ); + recv_!3( I, R, (Ci,Cr), {I}KDF(Ni, Nr, h(Gi,r), Ci, Cr), {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}sk(I) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman2.cpp new file mode 100644 index 0000000..e39a7b9 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman2.cpp @@ -0,0 +1,99 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Digital signature authentication (aggressive mode) with + * a modification suggested by Perlman et al. (last msg + * encrypted) + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define HDR (Ci,Cr) +#define SKEYIDi prf(Ni,Nr,Zi) +#define SKEYIDr prf(Ni,Nr,Zr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, {R}SKr, {HASH_Rr}sk(R) ); + send_!O2( O, O, {R}SKi, {HASH_Ri}sk(R) ); + + // msg 3 + recv_!O3( O, O, {I, {HASH_Ii}sk(I)}SKi ); + send_!O4( O, O, {I, {HASH_Ir}sk(I)}SKr ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-sig-a-perlman2(I, R) +{ + + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni ); + recv_!2( R, I, HDR, algo, Gr, Nr, {R}SKi, {HASH_Ri}sk(R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, HDR, {I, {HASH_Ii}sk(I)}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, HDR, algo, g(r), Nr, R, {R}SKr, {HASH_Rr}sk(R) ); + recv_!3( I, R, HDR, {I, {HASH_Ir}sk(I)}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman2.spdl new file mode 100644 index 0000000..c2edf7d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a-perlman2.spdl @@ -0,0 +1,130 @@ +# 1 "ikev1-sig-a-perlman2.cpp" +# 1 "<command-line>" +# 1 "ikev1-sig-a-perlman2.cpp" +# 18 "ikev1-sig-a-perlman2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 19 "ikev1-sig-a-perlman2.cpp" 2 +# 29 "ikev1-sig-a-perlman2.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {R}KDF(Ni, Nr, h(g(i),r), Ci, Cr), {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}sk(R) ); + send_!O2( O, O, {R}KDF(Ni, Nr, h(g(r),i), Ci, Cr), {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}sk(R) ); + + + recv_!O3( O, O, {I, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O4( O, O, {I, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} + + +protocol ikev1-sig-a-perlman2(I, R) +{ + + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni ); + recv_!2( R, I, (Ci,Cr), algo, Gr, Nr, {R}KDF(Ni, Nr, h(Gr,i), Ci, Cr), {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}sk(R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, (Ci,Cr), {I, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, (Ci,Cr), algo, g(r), Nr, R, {R}KDF(Ni, Nr, h(Gi,r), Ci, Cr), {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}sk(R) ); + recv_!3( I, R, (Ci,Cr), {I, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a1.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a1.cpp new file mode 100644 index 0000000..418492e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a1.cpp @@ -0,0 +1,98 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Digital signature authentication (aggressive mode) + * where the last message is not encrypted + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define HDR (Ci,Cr) +#define SKEYIDi prf(Ni,Nr,Zi) +#define SKEYIDr prf(Ni,Nr,Zr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, {HASH_Rr}sk(R) ); + send_!O2( O, O, {HASH_Ri}sk(R) ); + + // msg 3 + recv_!O3( O, O, {HASH_Ii}sk(I) ); + send_!O4( O, O, {HASH_Ir}sk(I) ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-sig-a1(I, R) +{ + + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni, I ); + recv_!2( R, I, HDR, algo, Gr, Nr, R, {HASH_Ri}sk(R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, HDR, {HASH_Ii}sk(I) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni, I ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, HDR, algo, g(r), Nr, R, {HASH_Rr}sk(R) ); + recv_!3( I, R, HDR, {HASH_Ir}sk(I) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a1.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a1.spdl new file mode 100644 index 0000000..327c4fe --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a1.spdl @@ -0,0 +1,130 @@ +# 1 "ikev1-sig-a1.cpp" +# 1 "<command-line>" +# 1 "ikev1-sig-a1.cpp" +# 17 "ikev1-sig-a1.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-sig-a1.cpp" 2 +# 28 "ikev1-sig-a1.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}sk(R) ); + send_!O2( O, O, {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}sk(R) ); + + + recv_!O3( O, O, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}sk(I) ); + send_!O4( O, O, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}sk(I) ); + + } + + +} + + +protocol ikev1-sig-a1(I, R) +{ + + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni, I ); + recv_!2( R, I, (Ci,Cr), algo, Gr, Nr, R, {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}sk(R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, (Ci,Cr), {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}sk(I) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni, I ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, (Ci,Cr), algo, g(r), Nr, R, {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}sk(R) ); + recv_!3( I, R, (Ci,Cr), {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}sk(I) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a2.cpp new file mode 100644 index 0000000..1c81dab --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a2.cpp @@ -0,0 +1,99 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Digital signature authentication (aggressive mode) + * where thelast message is encrypted with the session key + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define HDR (Ci,Cr) +#define SKEYIDi prf(Ni,Nr,Zi) +#define SKEYIDr prf(Ni,Nr,Zr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, {HASH_Rr}sk(R) ); + send_!O2( O, O, {HASH_Ri}sk(R) ); + + // msg 3 + recv_!O3( O, O, {{HASH_Ii}sk(I)}SKi ); + send_!O4( O, O, {{HASH_Ir}sk(I)}SKr ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-sig-a2(I, R) +{ + + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni, I ); + recv_!2( R, I, HDR, algo, Gr, Nr, R, {HASH_Ri}sk(R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, HDR, {{HASH_Ii}sk(I)}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni, I ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, HDR, algo, g(r), Nr, R, {HASH_Rr}sk(R) ); + recv_!3( I, R, HDR, {{HASH_Ir}sk(I)}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a2.spdl new file mode 100644 index 0000000..b0e6e07 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-a2.spdl @@ -0,0 +1,130 @@ +# 1 "ikev1-sig-a2.cpp" +# 1 "<command-line>" +# 1 "ikev1-sig-a2.cpp" +# 17 "ikev1-sig-a2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-sig-a2.cpp" 2 +# 29 "ikev1-sig-a2.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}sk(R) ); + send_!O2( O, O, {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}sk(R) ); + + + recv_!O3( O, O, {{prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O4( O, O, {{prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} + + +protocol ikev1-sig-a2(I, R) +{ + + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list, g(i), Ni, I ); + recv_!2( R, I, (Ci,Cr), algo, Gr, Nr, R, {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}sk(R) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!3( I, R, (Ci,Cr), {{prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list, Gi, Ni, I ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!2( R, I, (Ci,Cr), algo, g(r), Nr, R, {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}sk(R) ); + recv_!3( I, R, (Ci,Cr), {{prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m-perlman.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m-perlman.cpp new file mode 100644 index 0000000..4129ae2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m-perlman.cpp @@ -0,0 +1,100 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Digital signature authentication (aggressive mode) with + * a modification suggested by Perlman et al. + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define SKEYIDi prf(Ni,Nr,Zi) +#define SKEYIDr prf(Ni,Nr,Zr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 4 + recv_!O1( O, O, {R, {HASH_Rr}sk(R)}SKr ); + send_!O2( O, O, {R, {HASH_Ri}sk(R)}SKi ); + + // msg 5 + recv_!O3( O, O, {I, {HASH_Ii}sk(I)}SKi ); + send_!O4( O, O, {I, {HASH_Ir}sk(I)}SKr ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev1-sig-m-perlman(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), Ni ); + recv_!4( R, I, Ci, Cr, Gr, Nr, {R, {HASH_Ri}sk(R)}SKi ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!5( I, R, Ci, Cr, {I, {HASH_Ii}sk(I)}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, Ni ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!4( R, I, Ci, Cr, g(r), Nr, {R, {HASH_Rr}sk(R)}SKr ); + recv_!5( I, R, Ci, Cr, {I, {HASH_Ir}sk(I)}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m-perlman.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m-perlman.spdl new file mode 100644 index 0000000..321fc1b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m-perlman.spdl @@ -0,0 +1,133 @@ +# 1 "ikev1-sig-m-perlman.cpp" +# 1 "<command-line>" +# 1 "ikev1-sig-m-perlman.cpp" +# 17 "ikev1-sig-m-perlman.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 18 "ikev1-sig-m-perlman.cpp" 2 +# 27 "ikev1-sig-m-perlman.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {R, {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}sk(R)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + send_!O2( O, O, {R, {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}sk(R)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + + + recv_!O3( O, O, {I, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O4( O, O, {I, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} + + +protocol ikev1-sig-m-perlman(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, Ci, Cr, algo ); + send_3( I, R, Ci, Cr, g(i), Ni ); + recv_!4( R, I, Ci, Cr, Gr, Nr, {R, {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}sk(R)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!5( I, R, Ci, Cr, {I, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, Ci, Cr, algo ); + recv_3( I, R, Ci, Cr, Gi, Ni ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!4( R, I, Ci, Cr, g(r), Nr, {R, {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}sk(R)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + recv_!5( I, R, Ci, Cr, {I, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m.cpp new file mode 100644 index 0000000..f24b78f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m.cpp @@ -0,0 +1,102 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv1) + * @reference RFC 2409, + * Boyd C. and Mathuria A., Protocols for Authentication + * and Key Agreement + * @variant Digital signature authentication (aggressive mode) + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV1__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define HDR (Ci,Cr) +#define SKEYIDi prf(Ni,Nr,Zi) +#define SKEYIDr prf(Ni,Nr,Zr) +#define HASH_Ii prf(Ni, Nr, Zi, g(i), Gr, Ci, Cr, list, I) +#define HASH_Ir prf(Ni, Nr, Zr, Gi, g(r), Ci, Cr, list, I) +#define HASH_Ri prf(Ni, Nr, Zi, Gr, g(i), Cr, Ci, list, R) +#define HASH_Rr prf(Ni, Nr, Zr, g(r), Gi, Cr, Ci, list, R) + + +usertype String; +const list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 5 + recv_!O1( O, O, {I, {HASH_Ii}sk(I)}SKi ); + send_!O2( O, O, {I, {HASH_Ir}sk(I)}SKr ); + + // msg 6 + recv_!O3( O, O, {R, {HASH_Rr}sk(R)}SKr ); + send_!O4( O, O, {R, {HASH_Ri}sk(R)}SKi ); + + } +#undef Gi +#undef Gr +} + +protocol ikev1-sig-m(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, HDR, algo ); + send_3( I, R, HDR, g(i), Ni ); + recv_4( R, I, HDR, Gr, Nr ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!5( I, R, HDR, {I, {HASH_Ii}sk(I)}SKi ); + recv_!6( R, I, HDR, {R, {HASH_Ri}sk(R)}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, HDR, algo ); + recv_3( I, R, HDR, Gi, Ni ); + send_4( R, I, HDR, g(r), Nr ); + recv_!5( I, R, HDR, {I, {HASH_Ir}sk(I)}SKr ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!6( R, I, HDR, {R, {HASH_Rr}sk(R)}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m.spdl new file mode 100644 index 0000000..28150b0 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev1-sig-m.spdl @@ -0,0 +1,134 @@ +# 1 "ikev1-sig-m.cpp" +# 1 "<command-line>" +# 1 "ikev1-sig-m.cpp" +# 16 "ikev1-sig-m.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; + + + + + + + +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; + + + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 17 "ikev1-sig-m.cpp" 2 +# 28 "ikev1-sig-m.cpp" +usertype String; +const list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {I, {prf(Ni, Nr, h(g(r),i), g(i), g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!O2( O, O, {I, {prf(Ni, Nr, h(g(i),r), g(i), g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + + recv_!O3( O, O, {R, {prf(Ni, Nr, h(g(i),r), g(r), g(i), Cr, Ci, list, R)}sk(R)}KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + send_!O4( O, O, {R, {prf(Ni, Nr, h(g(r),i), g(r), g(i), Cr, Ci, list, R)}sk(R)}KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + + } + + +} + +protocol ikev1-sig-m(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, list ); + recv_2( R, I, (Ci,Cr), algo ); + send_3( I, R, (Ci,Cr), g(i), Ni ); + recv_4( R, I, (Ci,Cr), Gr, Nr ); + claim( I, Running, R, Ni, Nr, g(i), Gr, Ci, Cr ); + send_!5( I, R, (Ci,Cr), {I, {prf(Ni, Nr, h(Gr,i), g(i), Gr, Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + recv_!6( R, I, (Ci,Cr), {R, {prf(Ni, Nr, h(Gr,i), Gr, g(i), Cr, Ci, list, R)}sk(R)}KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni, Nr, g(i), Gr, Ci, Cr ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, list ); + send_2( R, I, (Ci,Cr), algo ); + recv_3( I, R, (Ci,Cr), Gi, Ni ); + send_4( R, I, (Ci,Cr), g(r), Nr ); + recv_!5( I, R, (Ci,Cr), {I, {prf(Ni, Nr, h(Gi,r), Gi, g(r), Ci, Cr, list, I)}sk(I)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + claim( R, Running, I, Ni, Nr, Gi, g(r), Ci, Cr ); + send_!6( R, I, (Ci,Cr), {R, {prf(Ni, Nr, h(Gi,r), g(r), Gi, Cr, Ci, list, R)}sk(R)}KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni, Nr, Gi, g(r), Ci, Cr ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child-nopfs.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child-nopfs.cpp new file mode 100644 index 0000000..9607308 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child-nopfs.cpp @@ -0,0 +1,78 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @subprotocol IKE Create Child SA + * @reference RFC 4306 + * @variant No perfect forward secrecy support + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2_CHILD_NOPFS__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +const SA3: Nonce; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling k(I,R) = k(R,I). + */ +protocol @executability(O) { + role O { + var Ni, Nr: Nonce; + var I, R: Agent; + + // msg 1 + recv_!O1( O, O, {SA3, Ni}k(I,R) ); + send_!O2( O, O, {SA3, Ni}k(R,I) ); + + // msg 2 + recv_!O3( O, O, {SA3, Nr}k(R,I) ); + send_!O4( O, O, {SA3, Nr}k(I,R) ); + + } +} + + +protocol ikev2-child-nopfs(I, R) +{ + + role I { + fresh Ni: Nonce; + var Nr: Nonce; + + /* IKE_SA_INIT */ + claim( I, Running, R,Ni ); + send_!1( I, R, {SA3, Ni}k(I,R) ); + recv_!2( R, I, {SA3, Nr}k(I,R) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,Nr ); + + } + + role R { + fresh Nr: Nonce; + var Ni: Nonce; + + recv_!1( I, R, {SA3, Ni}k(R,I) ); + claim( R, Running, I,Ni,Nr ); + send_!2( R, I, {SA3, Nr}k(R,I) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Ni ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child-nopfs.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child-nopfs.spdl new file mode 100644 index 0000000..d163151 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child-nopfs.spdl @@ -0,0 +1,112 @@ +# 1 "ikev2-child-nopfs.cpp" +# 1 "<command-line>" +# 1 "ikev2-child-nopfs.cpp" +# 15 "ikev2-child-nopfs.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 138 "common.h" + var I, R: Agent; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(k(I,R),Ni,Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(k(R,I),Ni,Nr) ); + + } + + +} +# 16 "ikev2-child-nopfs.cpp" 2 + + +const SA3: Nonce; + + + + + + +protocol @executability(O) { + role O { + var Ni, Nr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {SA3, Ni}k(I,R) ); + send_!O2( O, O, {SA3, Ni}k(R,I) ); + + + recv_!O3( O, O, {SA3, Nr}k(R,I) ); + send_!O4( O, O, {SA3, Nr}k(I,R) ); + + } +} + + +protocol ikev2-child-nopfs(I, R) +{ + + role I { + fresh Ni: Nonce; + var Nr: Nonce; + + + claim( I, Running, R,Ni ); + send_!1( I, R, {SA3, Ni}k(I,R) ); + recv_!2( R, I, {SA3, Nr}k(I,R) ); + + + claim( I, SKR, KDF(k(I,R),Ni,Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,Nr ); + + } + + role R { + fresh Nr: Nonce; + var Ni: Nonce; + + recv_!1( I, R, {SA3, Ni}k(R,I) ); + claim( R, Running, I,Ni,Nr ); + send_!2( R, I, {SA3, Nr}k(R,I) ); + + + claim( R, SKR, KDF(k(R,I),Ni,Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Ni ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child.cpp new file mode 100644 index 0000000..2378231 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child.cpp @@ -0,0 +1,87 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @subprotocol IKE Create Child SA + * @reference RFC 4306 + * @variant Supports perfect forward secrecy + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2_CHILD__ +#ifndef __ORACLE__ +#include "common.h" +#endif + + +usertype SecurityAssociation; +const SA1 ,SA2, SA3: SecurityAssociation; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling k(I,R) = k(R,I). + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr: Nonce; + var I, R: Agent; + + // msg 1 + recv_!O1( O, O, {SA3, Ni, g(i)}k(I,R) ); + send_!O2( O, O, {SA3, Ni, g(i)}k(R,I) ); + + // msg 2 + recv_!O3( O, O, {SA3, Nr, Gr}k(R,I) ); + send_!O4( O, O, {SA3, Nr, Gr}k(I,R) ); + + } +#undef Gi +#undef Gr +} + +// Note: SPIs not modeled as they would lead to trivial attacks where the adversary +// tampers with the SPIs (they are not subsequently authenticated) +protocol ikev2-child(I, R) +{ + + role I { + fresh i, Ni: Nonce; + var Nr: Nonce; + var Gr: Ticket; + + /* IKE_SA_INIT */ + claim( I, Running, R,Ni,g(i) ); + send_!1( I, R, {SA3, Ni, g(i)}k(I,R) ); + recv_!2( R, I, {SA3, Nr, Gr}k(I,R) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,g(i),Nr,Gr ); + + } + + role R { + fresh r, Nr: Nonce; + var Ni: Nonce; + var Gi: Ticket; + + recv_!1( I, R, {SA3, Ni, Gi}k(R,I) ); + claim( R, Running, I,Ni,Gi,Nr,g(r) ); + send_!2( R, I, {SA3, Nr, g(r)}k(R,I) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Ni,Gi ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child.spdl new file mode 100644 index 0000000..7c58959 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-child.spdl @@ -0,0 +1,121 @@ +# 1 "ikev2-child.cpp" +# 1 "<command-line>" +# 1 "ikev2-child.cpp" +# 15 "ikev2-child.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 135 "common.h" + var I, R: Agent; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(k(I,R),h(g(r),i),Ni,Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(k(R,I),h(g(i),r),Ni,Nr) ); + + } + + +} +# 16 "ikev2-child.cpp" 2 + + + +usertype SecurityAssociation; +const SA1 ,SA2, SA3: SecurityAssociation; + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {SA3, Ni, g(i)}k(I,R) ); + send_!O2( O, O, {SA3, Ni, g(i)}k(R,I) ); + + + recv_!O3( O, O, {SA3, Nr, g(r)}k(R,I) ); + send_!O4( O, O, {SA3, Nr, g(r)}k(I,R) ); + + } + + +} + + + +protocol ikev2-child(I, R) +{ + + role I { + fresh i, Ni: Nonce; + var Nr: Nonce; + var Gr: Ticket; + + + claim( I, Running, R,Ni,g(i) ); + send_!1( I, R, {SA3, Ni, g(i)}k(I,R) ); + recv_!2( R, I, {SA3, Nr, Gr}k(I,R) ); + + + claim( I, SKR, KDF(k(I,R),h(Gr,i),Ni,Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,g(i),Nr,Gr ); + + } + + role R { + fresh r, Nr: Nonce; + var Ni: Nonce; + var Gi: Ticket; + + recv_!1( I, R, {SA3, Ni, Gi}k(R,I) ); + claim( R, Running, I,Ni,Gi,Nr,g(r) ); + send_!2( R, I, {SA3, Nr, g(r)}k(R,I) ); + + + claim( R, SKR, KDF(k(R,I),h(Gi,r),Ni,Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Ni,Gi ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap.cpp new file mode 100644 index 0000000..7d8310b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap.cpp @@ -0,0 +1,131 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @subprotocol IKE EAP + * @reference RFC 4306 + * @variant Includes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr, EAP, EAPOK: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, R, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, R, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, EAP}SKr ); + send_!E4( E, E, {R, AUTHri, EAP}SKi ); + + // msg 5 + recv_!E5( E, E, {EAP}SKi ); + send_!E6( E, E, {EAP}SKr ); + + // msg 6 + recv_!E7( E, E, {EAPOK}SKr ); + send_!E8( E, E, {EAPOK}SKi ); + + // msg 7 + recv_!E9( E, E, {AUTHii}SKi ); + send_!EA( E, E, {AUTHir}SKr ); + + // msg 8 + send_!EB( E, E, {AUTHrr, SA2, TSi, TSr}SKr ); + send_!EC( E, E, {AUTHri, SA2, TSi, TSr}SKi ); + } +#undef Gi +#undef Gr +} + + +protocol ikev2-eap(I, R) +{ + + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var EAP, EAPOK: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + send_!3( I, R, HDR, {I, R, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, EAP}SKi ); + send_!5( I, R, HDR, {EAP}SKi ); + recv_!6( R, I, HDR, {EAPOK}SKi ); + claim( I, Running, R, Ni,g(i),Nr,Gr,TSi,TSr,EAP,EAPOK ); + send_!7( I, R, HDR, {AUTHii}SKi ); + recv_!8( R, I, HDR, {AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni,g(i),Nr,Gr,TSi,TSr,EAP,EAPOK ); + + } + + role R { + fresh EAP, EAPOK: Nonce; + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, R, SA2, TSi, TSr}SKr ); + send_!4( R, I, HDR, {R, AUTHrr, EAP}SKr ); + recv_!5( I, R, HDR, {EAP}SKr ); + send_!6( R, I, HDR, {EAPOK}SKr ); + recv_!7( I, R, HDR, {AUTHir}SKr ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr,EAP,EAPOK ); + send_!8( R, I, HDR, {AUTHrr, SA2, TSi, TSr}SKr ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr,EAP,EAPOK ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap.spdl new file mode 100644 index 0000000..43ec49a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap.spdl @@ -0,0 +1,160 @@ +# 1 "ikev2-eap.cpp" +# 1 "<command-line>" +# 1 "ikev2-eap.cpp" +# 15 "ikev2-eap.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-eap.cpp" 2 +# 24 "ikev2-eap.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr, EAP, EAPOK: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, R, SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, R, SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), EAP}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), EAP}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + + recv_!E5( E, E, {EAP}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E6( E, E, {EAP}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E7( E, E, {EAPOK}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E8( E, E, {EAPOK}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + + recv_!E9( E, E, {{SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I)}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!EA( E, E, {{SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I)}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + send_!EB( E, E, {{SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!EC( E, E, {{SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + } + + +} + + +protocol ikev2-eap(I, R) +{ + + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var EAP, EAPOK: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + send_!3( I, R, (SPIi,SPIr), {I, R, SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), EAP}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + send_!5( I, R, (SPIi,SPIr), {EAP}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!6( R, I, (SPIi,SPIr), {EAPOK}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + claim( I, Running, R, Ni,g(i),Nr,Gr,TSi,TSr,EAP,EAPOK ); + send_!7( I, R, (SPIi,SPIr), {{SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I)}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!8( R, I, (SPIi,SPIr), {{SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni,g(i),Nr,Gr,TSi,TSr,EAP,EAPOK ); + + } + + role R { + fresh EAP, EAPOK: Nonce; + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, R, SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + send_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), EAP}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + recv_!5( I, R, (SPIi,SPIr), {EAP}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + send_!6( R, I, (SPIi,SPIr), {EAPOK}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + recv_!7( I, R, (SPIi,SPIr), {{SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I)}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr,EAP,EAPOK ); + send_!8( R, I, (SPIi,SPIr), {{SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr,EAP,EAPOK ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap2.cpp new file mode 100644 index 0000000..c56855a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap2.cpp @@ -0,0 +1,138 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @subprotocol IKE EAP + * @reference RFC 4306 + * @variant Excludes optional payloads + **********************************************************************/ + +/** + * Modeling notes: + * - It's not clear what to put in the EAP payloads; we now model them + * as nonces, but maybe it is better to view them as a function of the + * actor. + */ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr, EAP, EAPOK: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, EAP}SKr ); + send_!E4( E, E, {R, AUTHri, EAP}SKi ); + + // msg 5 + recv_!E5( E, E, {EAP}SKi ); + send_!E6( E, E, {EAP}SKr ); + + // msg 6 + recv_!E7( E, E, {EAPOK}SKr ); + send_!E8( E, E, {EAPOK}SKi ); + + // msg 7 + recv_!E9( E, E, {AUTHii}SKi ); + send_!EA( E, E, {AUTHir}SKr ); + + // msg 8 + send_!EB( E, E, {AUTHrr, SA2, TSi, TSr}SKr ); + send_!EC( E, E, {AUTHri, SA2, TSi, TSr}SKi ); + } +#undef Gi +#undef Gr +} + + +protocol ikev2-eap2(I, R) +{ + + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var EAP, EAPOK: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + send_!3( I, R, HDR, {I, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, EAP}SKi ); + send_!5( I, R, HDR, {EAP}SKi ); + recv_!6( R, I, HDR, {EAPOK}SKi ); + claim( I, Running, R, Ni,g(i),Nr,Gr,TSi,TSr,EAP,EAPOK ); + send_!7( I, R, HDR, {AUTHii}SKi ); + recv_!8( R, I, HDR, {AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni,g(i),Nr,Gr,TSi,TSr,EAP,EAPOK ); + + } + + role R { + fresh EAP, EAPOK: Nonce; + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, SA2, TSi, TSr}SKr ); + send_!4( R, I, HDR, {R, AUTHrr, EAP}SKr ); + recv_!5( I, R, HDR, {EAP}SKr ); + send_!6( R, I, HDR, {EAPOK}SKr ); + recv_!7( I, R, HDR, {AUTHir}SKr ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr,EAP,EAPOK ); + send_!8( R, I, HDR, {AUTHrr, SA2, TSi, TSr}SKr ); + + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr,EAP,EAPOK ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap2.spdl new file mode 100644 index 0000000..1fbb580 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-eap2.spdl @@ -0,0 +1,160 @@ +# 1 "ikev2-eap2.cpp" +# 1 "<command-line>" +# 1 "ikev2-eap2.cpp" +# 22 "ikev2-eap2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 23 "ikev2-eap2.cpp" 2 +# 31 "ikev2-eap2.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr, EAP, EAPOK: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), EAP}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), EAP}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + + recv_!E5( E, E, {EAP}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E6( E, E, {EAP}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E7( E, E, {EAPOK}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E8( E, E, {EAPOK}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + + recv_!E9( E, E, {{SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I)}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!EA( E, E, {{SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I)}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + send_!EB( E, E, {{SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!EC( E, E, {{SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + } + + +} + + +protocol ikev2-eap2(I, R) +{ + + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var EAP, EAPOK: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + send_!3( I, R, (SPIi,SPIr), {I, SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), EAP}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + send_!5( I, R, (SPIi,SPIr), {EAP}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!6( R, I, (SPIi,SPIr), {EAPOK}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + claim( I, Running, R, Ni,g(i),Nr,Gr,TSi,TSr,EAP,EAPOK ); + send_!7( I, R, (SPIi,SPIr), {{SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I)}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!8( R, I, (SPIi,SPIr), {{SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni,g(i),Nr,Gr,TSi,TSr,EAP,EAPOK ); + + } + + role R { + fresh EAP, EAPOK: Nonce; + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + send_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), EAP}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + recv_!5( I, R, (SPIi,SPIr), {EAP}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + send_!6( R, I, (SPIi,SPIr), {EAPOK}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + recv_!7( I, R, (SPIi,SPIr), {{SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I)}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr,EAP,EAPOK ); + send_!8( R, I, (SPIi,SPIr), {{SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr,EAP,EAPOK ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac.cpp new file mode 100644 index 0000000..832afae --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac.cpp @@ -0,0 +1,104 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @subprotocol MAC authenticated IKEv2 + * @reference RFC 4306 + * @variant Includes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)) +#define AUTHir MAC(k(R,I), SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)) +#define AUTHri MAC(k(I,R), SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)) +#define AUTHrr MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev2-mac(I, R) +{ + + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + claim( I, Running, R, Ni,g(i),Nr,Gr,TSi,TSr); + send_!3( I, R, HDR, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni,g(i),Nr,Gr,TSi,TSr); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr); + send_!4( R, I, HDR, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac.spdl new file mode 100644 index 0000000..608d314 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac.spdl @@ -0,0 +1,133 @@ +# 1 "ikev2-mac.cpp" +# 1 "<command-line>" +# 1 "ikev2-mac.cpp" +# 15 "ikev2-mac.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-mac.cpp" 2 +# 24 "ikev2-mac.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, R, MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, R, MAC(k(R,I), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, MAC(k(I,R), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + } + + +} + + +protocol ikev2-mac(I, R) +{ + + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + claim( I, Running, R, Ni,g(i),Nr,Gr,TSi,TSr); + send_!3( I, R, (SPIi,SPIr), {I, R, MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, MAC(k(I,R), SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni,g(i),Nr,Gr,TSi,TSr); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, R, MAC(k(R,I), SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr); + send_!4( R, I, (SPIi,SPIr), {R, MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac2.cpp new file mode 100644 index 0000000..cb09faa --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac2.cpp @@ -0,0 +1,104 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @subprotocol MAC authenticated IKEv2 + * @reference RFC 4306 + * @variant Excludes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)) +#define AUTHir MAC(k(R,I), SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)) +#define AUTHri MAC(k(I,R), SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)) +#define AUTHrr MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev2-mac2(I, R) +{ + + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + claim( I, Running, R, Ni,g(i),Nr,Gr,TSi,TSr ); + send_!3( I, R, HDR, {I, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni,g(i),Nr,Gr,TSi,TSr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, AUTHir, SA2, TSi, TSr}SKr ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr ); + send_!4( R, I, HDR, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac2.spdl new file mode 100644 index 0000000..f6d3385 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mac2.spdl @@ -0,0 +1,133 @@ +# 1 "ikev2-mac2.cpp" +# 1 "<command-line>" +# 1 "ikev2-mac2.cpp" +# 15 "ikev2-mac2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-mac2.cpp" 2 +# 24 "ikev2-mac2.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, MAC(k(R,I), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, MAC(k(I,R), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + } + + +} + + +protocol ikev2-mac2(I, R) +{ + + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + claim( I, Running, R, Ni,g(i),Nr,Gr,TSi,TSr ); + send_!3( I, R, (SPIi,SPIr), {I, MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, MAC(k(I,R), SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R, Ni,g(i),Nr,Gr,TSi,TSr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, MAC(k(R,I), SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr ); + send_!4( R, I, (SPIi,SPIr), {R, MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig.cpp new file mode 100644 index 0000000..519f93a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig.cpp @@ -0,0 +1,104 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @reference RFC 4306 + * @variant Initiator authenticates itself using message + * authentication codes while responder uses digital + * signatures. Includes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)) +#define AUTHir MAC(k(R,I), SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev2-mactosig(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, SPIi, SPIr, SA1, Gr, Nr ); + + /* IKE_AUTH */ + claim( I, Running, R,Ni,g(i),Nr,Gr,TSi,TSr ); + send_!3( I, R, SPIi, SPIr, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, SPIi, SPIr, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,g(i),Nr,Gr,TSi,TSr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, SPIi, SPIr, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, SPIi, SPIr, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr ); + send_!4( R, I, SPIi, SPIr, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig.spdl new file mode 100644 index 0000000..388562e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig.spdl @@ -0,0 +1,132 @@ +# 1 "ikev2-mactosig.cpp" +# 1 "<command-line>" +# 1 "ikev2-mactosig.cpp" +# 16 "ikev2-mactosig.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 17 "ikev2-mactosig.cpp" 2 +# 25 "ikev2-mactosig.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, R, MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, R, MAC(k(R,I), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + } + + +} + + +protocol ikev2-mactosig(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, SPIi, SPIr, SA1, Gr, Nr ); + + + claim( I, Running, R,Ni,g(i),Nr,Gr,TSi,TSr ); + send_!3( I, R, SPIi, SPIr, {I, R, MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, SPIi, SPIr, {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,g(i),Nr,Gr,TSi,TSr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, SPIi, SPIr, SA1, g(r), Nr ); + + + recv_!3( I, R, SPIi, SPIr, {I, R, MAC(k(R,I), SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr ); + send_!4( R, I, SPIi, SPIr, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig2.cpp new file mode 100644 index 0000000..73b20f5 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig2.cpp @@ -0,0 +1,103 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @reference RFC 4306 + * @variant Initiator authenticates itself using message + * authentication codes while responder uses digital + * signatures. Excludes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)) +#define AUTHir MAC(k(R,I), SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + } +#undef Gi +#undef Gr +} + +protocol ikev2-mactosig2(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, SPIi, SPIr, SA1, Gr, Nr ); + + /* IKE_AUTH */ + claim( I, Running, R,Ni,g(i),Nr,Gr,TSi,TSr ); + send_!3( I, R, SPIi, SPIr, {I, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, SPIi, SPIr, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,g(i),Nr,Gr,TSi,TSr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, SPIi, SPIr, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, SPIi, SPIr, {I, AUTHir, SA2, TSi, TSr}SKr ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr ); + send_!4( R, I, SPIi, SPIr, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig2.spdl new file mode 100644 index 0000000..92864ab --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-mactosig2.spdl @@ -0,0 +1,131 @@ +# 1 "ikev2-mactosig2.cpp" +# 1 "<command-line>" +# 1 "ikev2-mactosig2.cpp" +# 16 "ikev2-mactosig2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 17 "ikev2-mactosig2.cpp" 2 +# 25 "ikev2-mactosig2.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, MAC(k(R,I), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + } + + +} + +protocol ikev2-mactosig2(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, SPIi, SPIr, SA1, Gr, Nr ); + + + claim( I, Running, R,Ni,g(i),Nr,Gr,TSi,TSr ); + send_!3( I, R, SPIi, SPIr, {I, MAC(k(I,R), SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, SPIi, SPIr, {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,g(i),Nr,Gr,TSi,TSr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, SPIi, SPIr, SA1, g(r), Nr ); + + + recv_!3( I, R, SPIi, SPIr, {I, MAC(k(R,I), SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr ); + send_!4( R, I, SPIi, SPIr, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child-composed.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child-composed.cpp new file mode 100644 index 0000000..62ddf6f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child-composed.cpp @@ -0,0 +1,138 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @reference RFC 4306 + * @variant Combination of signature authenticated IKEv2 and + * CREATE_CHILD_SA, includes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) +#define KEYMATi KDF(Ni, Nr, Zi, h(Gt,j), Mi, Mr) +#define KEYMATr KDF(Ni, Nr, Zr, h(Gi,t), Mi, Mr) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + // msg 5 + recv_!E5( E, E, {SA3, Mi, g(j), TSi, TSr}SKi ); + send_!E6( E, E, {SA3, Mi, g(j), TSi, TSr}SKr ); + + // msg 6 + recv_!E7( E, E, {SA3, Mr, g(t), TSi, TSr}SKr ); + send_!E8( E, E, {SA3, Mr, g(t), TSi, TSr}SKr ); + } +#undef Gi +#undef Gr +} +protocol @ora(S) { +#define Gi g(i) +#define Gj g(j) +#define Gr g(r) +#define Gt g(t) + role S { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + + recv_!S1( S, S, KDF(Ni, Nr, Zi, h(Gt,j), Mi, Mr) ); + send_!S2( S, S, KDF(Ni, Nr, Zr, h(Gj,t), Mi, Mr) ); + } +#undef Gi +#undef Gj +#undef Gr +#undef Gt +} + + +protocol ikev2-sig-child(I, R) +{ + role I { + fresh i, j, Ni, Mi, SPIi: Nonce; + var Nr, Mr, SPIr: Nonce; + var Gr, Gt: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + send_!3( I, R, HDR, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* CREATE_CHILD_SA */ + claim( I, Running, R,g(i),g(j),Gr ); + send_!5( I, R, HDR, {SA3, Mi, g(j), TSi, TSr}SKi ); + recv_!6( R, I, HDR, {SA3, Mr, Gt, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + claim( I, SKR, KEYMATi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),g(j),Gr,Gt ); + + } + + role R { + fresh r, t, Nr, Mr, SPIr: Nonce; + var Ni, Mi, SPIi: Nonce; + var Gi, Gj: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + send_!4( R, I, HDR, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* CREATE_CHILD_SA */ + recv_!5( I, R, HDR, {SA3, Mi, Gj, TSi, TSr}SKr ); + claim( R, Running, I,Gi,Gj,g(r),g(t) ); + send_!6( R, I, HDR, {SA3, Mr, g(t), TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + claim( R, SKR, KEYMATr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,Gj,g(r) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child-composed.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child-composed.spdl new file mode 100644 index 0000000..392c995 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child-composed.spdl @@ -0,0 +1,165 @@ +# 1 "ikev2-sig-child-composed.cpp" +# 1 "<command-line>" +# 1 "ikev2-sig-child-composed.cpp" +# 15 "ikev2-sig-child-composed.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-sig-child-composed.cpp" 2 +# 26 "ikev2-sig-child-composed.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + + recv_!E5( E, E, {SA3, Mi, g(j), TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E6( E, E, {SA3, Mi, g(j), TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E7( E, E, {SA3, Mr, g(t), TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E8( E, E, {SA3, Mr, g(t), TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + } + + +} +protocol @ora(S) { + + + + + role S { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + + recv_!S1( S, S, KDF(Ni, Nr, h(g(r),i), h(g(t),j), Mi, Mr) ); + send_!S2( S, S, KDF(Ni, Nr, h(g(i),r), h(g(j),t), Mi, Mr) ); + } + + + + +} + + +protocol ikev2-sig-child(I, R) +{ + role I { + fresh i, j, Ni, Mi, SPIi: Nonce; + var Nr, Mr, SPIr: Nonce; + var Gr, Gt: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + send_!3( I, R, (SPIi,SPIr), {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, Running, R,g(i),g(j),Gr ); + send_!5( I, R, (SPIi,SPIr), {SA3, Mi, g(j), TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!6( R, I, (SPIi,SPIr), {SA3, Mr, Gt, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), h(Gt,j), Mi, Mr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),g(j),Gr,Gt ); + + } + + role R { + fresh r, t, Nr, Mr, SPIr: Nonce; + var Ni, Mi, SPIi: Nonce; + var Gi, Gj: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, R, {SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + send_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + recv_!5( I, R, (SPIi,SPIr), {SA3, Mi, Gj, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I,Gi,Gj,g(r),g(t) ); + send_!6( R, I, (SPIi,SPIr), {SA3, Mr, g(t), TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), h(Gi,t), Mi, Mr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,Gj,g(r) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child.cpp new file mode 100644 index 0000000..62ddf6f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child.cpp @@ -0,0 +1,138 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @reference RFC 4306 + * @variant Combination of signature authenticated IKEv2 and + * CREATE_CHILD_SA, includes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) +#define KEYMATi KDF(Ni, Nr, Zi, h(Gt,j), Mi, Mr) +#define KEYMATr KDF(Ni, Nr, Zr, h(Gi,t), Mi, Mr) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + // msg 5 + recv_!E5( E, E, {SA3, Mi, g(j), TSi, TSr}SKi ); + send_!E6( E, E, {SA3, Mi, g(j), TSi, TSr}SKr ); + + // msg 6 + recv_!E7( E, E, {SA3, Mr, g(t), TSi, TSr}SKr ); + send_!E8( E, E, {SA3, Mr, g(t), TSi, TSr}SKr ); + } +#undef Gi +#undef Gr +} +protocol @ora(S) { +#define Gi g(i) +#define Gj g(j) +#define Gr g(r) +#define Gt g(t) + role S { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + + recv_!S1( S, S, KDF(Ni, Nr, Zi, h(Gt,j), Mi, Mr) ); + send_!S2( S, S, KDF(Ni, Nr, Zr, h(Gj,t), Mi, Mr) ); + } +#undef Gi +#undef Gj +#undef Gr +#undef Gt +} + + +protocol ikev2-sig-child(I, R) +{ + role I { + fresh i, j, Ni, Mi, SPIi: Nonce; + var Nr, Mr, SPIr: Nonce; + var Gr, Gt: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + send_!3( I, R, HDR, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* CREATE_CHILD_SA */ + claim( I, Running, R,g(i),g(j),Gr ); + send_!5( I, R, HDR, {SA3, Mi, g(j), TSi, TSr}SKi ); + recv_!6( R, I, HDR, {SA3, Mr, Gt, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + claim( I, SKR, KEYMATi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),g(j),Gr,Gt ); + + } + + role R { + fresh r, t, Nr, Mr, SPIr: Nonce; + var Ni, Mi, SPIi: Nonce; + var Gi, Gj: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + send_!4( R, I, HDR, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* CREATE_CHILD_SA */ + recv_!5( I, R, HDR, {SA3, Mi, Gj, TSi, TSr}SKr ); + claim( R, Running, I,Gi,Gj,g(r),g(t) ); + send_!6( R, I, HDR, {SA3, Mr, g(t), TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + claim( R, SKR, KEYMATr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,Gj,g(r) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child.spdl new file mode 100644 index 0000000..f9db4cf --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child.spdl @@ -0,0 +1,165 @@ +# 1 "ikev2-sig-child.cpp" +# 1 "<command-line>" +# 1 "ikev2-sig-child.cpp" +# 15 "ikev2-sig-child.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-sig-child.cpp" 2 +# 26 "ikev2-sig-child.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + + recv_!E5( E, E, {SA3, Mi, g(j), TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E6( E, E, {SA3, Mi, g(j), TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E7( E, E, {SA3, Mr, g(t), TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E8( E, E, {SA3, Mr, g(t), TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + } + + +} +protocol @ora(S) { + + + + + role S { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + + recv_!S1( S, S, KDF(Ni, Nr, h(g(r),i), h(g(t),j), Mi, Mr) ); + send_!S2( S, S, KDF(Ni, Nr, h(g(i),r), h(g(j),t), Mi, Mr) ); + } + + + + +} + + +protocol ikev2-sig-child(I, R) +{ + role I { + fresh i, j, Ni, Mi, SPIi: Nonce; + var Nr, Mr, SPIr: Nonce; + var Gr, Gt: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + send_!3( I, R, (SPIi,SPIr), {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, Running, R,g(i),g(j),Gr ); + send_!5( I, R, (SPIi,SPIr), {SA3, Mi, g(j), TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!6( R, I, (SPIi,SPIr), {SA3, Mr, Gt, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), h(Gt,j), Mi, Mr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),g(j),Gr,Gt ); + + } + + role R { + fresh r, t, Nr, Mr, SPIr: Nonce; + var Ni, Mi, SPIi: Nonce; + var Gi, Gj: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, R, {SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + send_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + recv_!5( I, R, (SPIi,SPIr), {SA3, Mi, Gj, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I,Gi,Gj,g(r),g(t) ); + send_!6( R, I, (SPIi,SPIr), {SA3, Mr, g(t), TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), h(Gi,t), Mi, Mr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,Gj,g(r) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2-composed.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2-composed.cpp new file mode 100644 index 0000000..621e7f6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2-composed.cpp @@ -0,0 +1,138 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @reference RFC 4306 + * @variant Combination of signature authenticated IKEv2 and + * CREATE_CHILD_SA, excludes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) +#define KEYMATi KDF(Ni, Nr, Zi, h(Gt,j), Mi, Mr) +#define KEYMATr KDF(Ni, Nr, Zr, h(Gi,t), Mi, Mr) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + // msg 5 + recv_!E5( E, E, {SA3, Mi, g(j)}SKi ); + send_!E6( E, E, {SA3, Mi, g(j)}SKr ); + + // msg 6 + recv_!E7( E, E, {SA3, Mr, g(t)}SKr ); + send_!E8( E, E, {SA3, Mr, g(t)}SKr ); + } +#undef Gi +#undef Gr +} +protocol @ora(S) { +#define Gi g(i) +#define Gj g(j) +#define Gr g(r) +#define Gt g(t) + role S { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + + recv_!S1( S, S, KDF(Ni, Nr, Zi, h(Gt,j), Mi, Mr) ); + send_!S2( S, S, KDF(Ni, Nr, Zr, h(Gj,t), Mi, Mr) ); + } +#undef Gi +#undef Gj +#undef Gr +#undef Gt +} + + +protocol ikev2-sig-child2(I, R) +{ + role I { + fresh i, j, Ni, Mi, SPIi: Nonce; + var Nr, Mr, SPIr: Nonce; + var Gr, Gt: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + send_!3( I, R, HDR, {I, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* CREATE_CHILD_SA */ + claim( I, Running, R,g(i),g(j),Gr ); + send_!5( I, R, HDR, {SA3, Mi, g(j)}SKi ); + recv_!6( R, I, HDR, {SA3, Mr, Gt}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + claim( I, SKR, KEYMATi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),g(j),Gr,Gt ); + + } + + role R { + fresh r, t, Nr, Mr, SPIr: Nonce; + var Ni, Mi, SPIi: Nonce; + var Gi, Gj: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, AUTHir, SA2, TSi, TSr}SKr ); + send_!4( R, I, HDR, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* CREATE_CHILD_SA */ + recv_!5( I, R, HDR, {SA3, Mi, Gj}SKr ); + claim( R, Running, I,Gi,Gj,g(r),g(t) ); + send_!6( R, I, HDR, {SA3, Mr, g(t)}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + claim( R, SKR, KEYMATr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,Gj,g(r) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2-composed.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2-composed.spdl new file mode 100644 index 0000000..49df999 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2-composed.spdl @@ -0,0 +1,165 @@ +# 1 "ikev2-sig-child2-composed.cpp" +# 1 "<command-line>" +# 1 "ikev2-sig-child2-composed.cpp" +# 15 "ikev2-sig-child2-composed.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-sig-child2-composed.cpp" 2 +# 26 "ikev2-sig-child2-composed.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + + recv_!E5( E, E, {SA3, Mi, g(j)}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E6( E, E, {SA3, Mi, g(j)}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E7( E, E, {SA3, Mr, g(t)}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E8( E, E, {SA3, Mr, g(t)}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + } + + +} +protocol @ora(S) { + + + + + role S { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + + recv_!S1( S, S, KDF(Ni, Nr, h(g(r),i), h(g(t),j), Mi, Mr) ); + send_!S2( S, S, KDF(Ni, Nr, h(g(i),r), h(g(j),t), Mi, Mr) ); + } + + + + +} + + +protocol ikev2-sig-child2(I, R) +{ + role I { + fresh i, j, Ni, Mi, SPIi: Nonce; + var Nr, Mr, SPIr: Nonce; + var Gr, Gt: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + send_!3( I, R, (SPIi,SPIr), {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, Running, R,g(i),g(j),Gr ); + send_!5( I, R, (SPIi,SPIr), {SA3, Mi, g(j)}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!6( R, I, (SPIi,SPIr), {SA3, Mr, Gt}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), h(Gt,j), Mi, Mr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),g(j),Gr,Gt ); + + } + + role R { + fresh r, t, Nr, Mr, SPIr: Nonce; + var Ni, Mi, SPIi: Nonce; + var Gi, Gj: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, {SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + send_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + recv_!5( I, R, (SPIi,SPIr), {SA3, Mi, Gj}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I,Gi,Gj,g(r),g(t) ); + send_!6( R, I, (SPIi,SPIr), {SA3, Mr, g(t)}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), h(Gi,t), Mi, Mr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,Gj,g(r) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2.cpp new file mode 100644 index 0000000..621e7f6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2.cpp @@ -0,0 +1,138 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @reference RFC 4306 + * @variant Combination of signature authenticated IKEv2 and + * CREATE_CHILD_SA, excludes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) +#define KEYMATi KDF(Ni, Nr, Zi, h(Gt,j), Mi, Mr) +#define KEYMATr KDF(Ni, Nr, Zr, h(Gi,t), Mi, Mr) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + // msg 5 + recv_!E5( E, E, {SA3, Mi, g(j)}SKi ); + send_!E6( E, E, {SA3, Mi, g(j)}SKr ); + + // msg 6 + recv_!E7( E, E, {SA3, Mr, g(t)}SKr ); + send_!E8( E, E, {SA3, Mr, g(t)}SKr ); + } +#undef Gi +#undef Gr +} +protocol @ora(S) { +#define Gi g(i) +#define Gj g(j) +#define Gr g(r) +#define Gt g(t) + role S { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + + recv_!S1( S, S, KDF(Ni, Nr, Zi, h(Gt,j), Mi, Mr) ); + send_!S2( S, S, KDF(Ni, Nr, Zr, h(Gj,t), Mi, Mr) ); + } +#undef Gi +#undef Gj +#undef Gr +#undef Gt +} + + +protocol ikev2-sig-child2(I, R) +{ + role I { + fresh i, j, Ni, Mi, SPIi: Nonce; + var Nr, Mr, SPIr: Nonce; + var Gr, Gt: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + send_!3( I, R, HDR, {I, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* CREATE_CHILD_SA */ + claim( I, Running, R,g(i),g(j),Gr ); + send_!5( I, R, HDR, {SA3, Mi, g(j)}SKi ); + recv_!6( R, I, HDR, {SA3, Mr, Gt}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + claim( I, SKR, KEYMATi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),g(j),Gr,Gt ); + + } + + role R { + fresh r, t, Nr, Mr, SPIr: Nonce; + var Ni, Mi, SPIi: Nonce; + var Gi, Gj: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, AUTHir, SA2, TSi, TSr}SKr ); + send_!4( R, I, HDR, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* CREATE_CHILD_SA */ + recv_!5( I, R, HDR, {SA3, Mi, Gj}SKr ); + claim( R, Running, I,Gi,Gj,g(r),g(t) ); + send_!6( R, I, HDR, {SA3, Mr, g(t)}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + claim( R, SKR, KEYMATr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,Gj,g(r) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2.spdl new file mode 100644 index 0000000..aa8642f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig-child2.spdl @@ -0,0 +1,165 @@ +# 1 "ikev2-sig-child2.cpp" +# 1 "<command-line>" +# 1 "ikev2-sig-child2.cpp" +# 15 "ikev2-sig-child2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-sig-child2.cpp" 2 +# 26 "ikev2-sig-child2.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + + recv_!E5( E, E, {SA3, Mi, g(j)}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E6( E, E, {SA3, Mi, g(j)}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E7( E, E, {SA3, Mr, g(t)}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E8( E, E, {SA3, Mr, g(t)}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + } + + +} +protocol @ora(S) { + + + + + role S { + var i, j, r, t, Mi, Ni, Mr, Nr, SPIi, SPIr: Nonce; + + recv_!S1( S, S, KDF(Ni, Nr, h(g(r),i), h(g(t),j), Mi, Mr) ); + send_!S2( S, S, KDF(Ni, Nr, h(g(i),r), h(g(j),t), Mi, Mr) ); + } + + + + +} + + +protocol ikev2-sig-child2(I, R) +{ + role I { + fresh i, j, Ni, Mi, SPIi: Nonce; + var Nr, Mr, SPIr: Nonce; + var Gr, Gt: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + send_!3( I, R, (SPIi,SPIr), {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, Running, R,g(i),g(j),Gr ); + send_!5( I, R, (SPIi,SPIr), {SA3, Mi, g(j)}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!6( R, I, (SPIi,SPIr), {SA3, Mr, Gt}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), h(Gt,j), Mi, Mr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),g(j),Gr,Gt ); + + } + + role R { + fresh r, t, Nr, Mr, SPIr: Nonce; + var Ni, Mi, SPIi: Nonce; + var Gi, Gj: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, {SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + send_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + recv_!5( I, R, (SPIi,SPIr), {SA3, Mi, Gj}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I,Gi,Gj,g(r),g(t) ); + send_!6( R, I, (SPIi,SPIr), {SA3, Mr, g(t)}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), h(Gi,t), Mi, Mr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,Gj,g(r) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig.cpp new file mode 100644 index 0000000..68e7326 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig.cpp @@ -0,0 +1,103 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @subprotocol Signature authenticated IKEv2 + * @reference RFC 4306 + * @variant Includes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev2-sig(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + claim( I, Running, R,g(i),Gr,Ni,Nr ); + send_!3( I, R, HDR, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),Gr,Ni,Nr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + claim( R, Running, I,Gi,g(r),Ni,Nr ); + send_!4( R, I, HDR, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,g(r),Ni,Nr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig.spdl new file mode 100644 index 0000000..baaba1a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig.spdl @@ -0,0 +1,132 @@ +# 1 "ikev2-sig.cpp" +# 1 "<command-line>" +# 1 "ikev2-sig.cpp" +# 15 "ikev2-sig.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-sig.cpp" 2 +# 24 "ikev2-sig.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + } + + +} + + +protocol ikev2-sig(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + claim( I, Running, R,g(i),Gr,Ni,Nr ); + send_!3( I, R, (SPIi,SPIr), {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),Gr,Ni,Nr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, R, {SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I,Gi,g(r),Ni,Nr ); + send_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,g(r),Ni,Nr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig2.cpp new file mode 100644 index 0000000..e2e02b7 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig2.cpp @@ -0,0 +1,103 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @subprotocol Signature authenticated IKEv2 + * @reference RFC 4306 + * @variant Excludes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)}sk(R) +#define AUTHrr {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)}sk(R) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev2-sig2(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, HDR, SA1, Gr, Nr ); + + /* IKE_AUTH */ + claim( I, Running, R,Ni,g(i),Nr,Gr,TSi,TSr ); + send_!3( I, R, HDR, {I, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, HDR, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,g(i),Nr,Gr,TSi,TSr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, HDR, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, HDR, {I, AUTHir, SA2, TSi, TSr}SKr ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr ); + send_!4( R, I, HDR, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig2.spdl new file mode 100644 index 0000000..0825976 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sig2.spdl @@ -0,0 +1,132 @@ +# 1 "ikev2-sig2.cpp" +# 1 "<command-line>" +# 1 "ikev2-sig2.cpp" +# 15 "ikev2-sig2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 16 "ikev2-sig2.cpp" 2 +# 24 "ikev2-sig2.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + } + + +} + + +protocol ikev2-sig2(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, (SPIi,SPIr), SA1, Gr, Nr ); + + + claim( I, Running, R,Ni,g(i),Nr,Gr,TSi,TSr ); + send_!3( I, R, (SPIi,SPIr), {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,Ni,g(i),Nr,Gr,TSi,TSr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, (SPIi,SPIr), SA1, g(r), Nr ); + + + recv_!3( I, R, (SPIi,SPIr), {I, {SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I, Ni,Gi,Nr,g(r),TSi,TSr ); + send_!4( R, I, (SPIi,SPIr), {R, {SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)}sk(R), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I, Ni,Gi,Nr,g(r),TSi,TSr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac.cpp new file mode 100644 index 0000000..dc7a059 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac.cpp @@ -0,0 +1,104 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @reference RFC 4306 + * @variant Initiator authenticates itself using digital signatures + * while responder uses message authentication codes. + * Includes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri MAC(k(I,R), SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)) +#define AUTHrr MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev2-sigtomac(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, SPIi, SPIr, SA1, Gr, Nr ); + + /* IKE_AUTH */ + claim( I, Running, R,g(i),Gr,Ni,Nr ); + send_!3( I, R, SPIi, SPIr, {I, R, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, SPIi, SPIr, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),Gr,Ni,Nr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, SPIi, SPIr, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, SPIi, SPIr, {I, R, AUTHir, SA2, TSi, TSr}SKr ); + claim( R, Running, I,Gi,g(r),Ni,Nr ); + send_!4( R, I, SPIi, SPIr, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,g(r),Ni,Nr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac.spdl new file mode 100644 index 0000000..9d40a3a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac.spdl @@ -0,0 +1,132 @@ +# 1 "ikev2-sigtomac.cpp" +# 1 "<command-line>" +# 1 "ikev2-sigtomac.cpp" +# 16 "ikev2-sigtomac.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 17 "ikev2-sigtomac.cpp" 2 +# 25 "ikev2-sigtomac.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, MAC(k(I,R), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + } + + +} + + +protocol ikev2-sigtomac(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, SPIi, SPIr, SA1, Gr, Nr ); + + + claim( I, Running, R,g(i),Gr,Ni,Nr ); + send_!3( I, R, SPIi, SPIr, {I, R, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, SPIi, SPIr, {R, MAC(k(I,R), SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),Gr,Ni,Nr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, SPIi, SPIr, SA1, g(r), Nr ); + + + recv_!3( I, R, SPIi, SPIr, {I, R, {SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I,Gi,g(r),Ni,Nr ); + send_!4( R, I, SPIi, SPIr, {R, MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,g(r),Ni,Nr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac2.cpp b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac2.cpp new file mode 100644 index 0000000..bccbab3 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac2.cpp @@ -0,0 +1,104 @@ +/********************************************************************** + * @protocol Internet Key Exchange Protocol (IKEv2) + * @reference RFC 4306 + * @variant Initiator authenticates itself using digital signatures + * while responder uses message authentication codes. + * Excludes optional payloads + **********************************************************************/ + +/** + * MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + */ + +#define __IKEV2__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define AUTHii {SPIi, O, SA1, g(i), Ni, Nr, prf(SKi, I)}sk(I) +#define AUTHir {SPIi, O, SA1, Gi, Ni, Nr, prf(SKr, I)}sk(I) +#define AUTHri MAC(k(I,R), SPIi, SPIr, SA1, Gr, Nr, Ni, prf(SKi, R)) +#define AUTHrr MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(SKr, R)) + + +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(E) { +#define Gi g(i) +#define Gr g(r) + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!E1( E, E, {I, AUTHii, SA2, TSi, TSr}SKi ); + send_!E2( E, E, {I, AUTHir, SA2, TSi, TSr}SKr ); + + // msg 4 + recv_!E3( E, E, {R, AUTHrr, SA2, TSi, TSr}SKr ); + send_!E4( E, E, {R, AUTHri, SA2, TSi, TSr}SKi ); + + } +#undef Gi +#undef Gr +} + + +protocol ikev2-sigtomac2(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + /* IKE_SA_INIT */ + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, SPIi, SPIr, SA1, Gr, Nr ); + + /* IKE_AUTH */ + claim( I, Running, R,g(i),Gr,Ni,Nr ); + send_!3( I, R, SPIi, SPIr, {I, AUTHii, SA2, TSi, TSr}SKi ); + recv_!4( R, I, SPIi, SPIr, {R, AUTHri, SA2, TSi, TSr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),Gr,Ni,Nr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + /* IKE_SA_INIT */ + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, SPIi, SPIr, SA1, g(r), Nr ); + + /* IKE_AUTH */ + recv_!3( I, R, SPIi, SPIr, {I, AUTHir, SA2, TSi, TSr}SKr ); + claim( R, Running, I,Gi,g(r),Ni,Nr ); + send_!4( R, I, SPIi, SPIr, {R, AUTHrr, SA2, TSi, TSr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,g(r),Ni,Nr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac2.spdl b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac2.spdl new file mode 100644 index 0000000..99ad18c --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/ikev2-sigtomac2.spdl @@ -0,0 +1,132 @@ +# 1 "ikev2-sigtomac2.cpp" +# 1 "<command-line>" +# 1 "ikev2-sigtomac2.cpp" +# 16 "ikev2-sigtomac2.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 43 "common.h" +hashfunction MAC; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 132 "common.h" + var SPIi, SPIr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + } + + +} +# 17 "ikev2-sigtomac2.cpp" 2 +# 25 "ikev2-sigtomac2.cpp" +usertype Number, SecurityAssociation, TrafficSelector; +const O: Number; +const SA1 ,SA2, SA3: SecurityAssociation; +const TSi, TSr: TrafficSelector; + + + + + + +protocol @executability(E) { + + + role E { + var i, r, Ni, Nr, SPIi, SPIr: Nonce; + var I, R: Agent; + + + recv_!E1( E, E, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + send_!E2( E, E, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + + + recv_!E3( E, E, {R, MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(i),r),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(i),r),SPIi,SPIr) ); + send_!E4( E, E, {R, MAC(k(I,R), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(g(r),i),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(g(r),i),SPIi,SPIr) ); + + } + + +} + + +protocol ikev2-sigtomac2(I, R) +{ + role I { + fresh i, Ni, SPIi: Nonce; + var Nr, SPIr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, SPIi, O, SA1, g(i), Ni ); + recv_2( R, I, SPIi, SPIr, SA1, Gr, Nr ); + + + claim( I, Running, R,g(i),Gr,Ni,Nr ); + send_!3( I, R, SPIi, SPIr, {I, {SPIi, O, SA1, g(i), Ni, Nr, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + recv_!4( R, I, SPIi, SPIr, {R, MAC(k(I,R), SPIi, SPIr, SA1, Gr, Nr, Ni, prf(KDF(Ni,Nr,h(Gr,i),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + + claim( I, SKR, KDF(Ni,Nr,h(Gr,i),SPIi,SPIr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + claim( I, Commit, R,g(i),Gr,Ni,Nr ); + + } + + role R { + fresh r, Nr, SPIr: Nonce; + var Ni, SPIi: Nonce; + var Gi: Ticket; + + + + recv_1( I, R, SPIi, O, SA1, Gi, Ni ); + send_2( R, I, SPIi, SPIr, SA1, g(r), Nr ); + + + recv_!3( I, R, SPIi, SPIr, {I, {SPIi, O, SA1, Gi, Ni, Nr, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), I)}sk(I), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + claim( R, Running, I,Gi,g(r),Ni,Nr ); + send_!4( R, I, SPIi, SPIr, {R, MAC(k(R,I), SPIi, SPIr, SA1, g(r), Nr, Ni, prf(KDF(Ni,Nr,h(Gi,r),SPIi,SPIr), R)), SA2, TSi, TSr}KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + + claim( R, SKR, KDF(Ni,Nr,h(Gi,r),SPIi,SPIr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + claim( R, Commit, I,Gi,g(r),Ni,Nr ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/jfki-core.cpp b/Vagrant Files/files/scyther/Protocols/IKE/jfki-core.cpp new file mode 100644 index 0000000..d6c2abf --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/jfki-core.cpp @@ -0,0 +1,54 @@ +/** HEADDOC + * @protocol Just Fast Keying + * @reference Aiello et al., Just Fast Keying: Key Agreement In A Hostile + * Internet + * @description + * @variant Core cryptographic protocol of JFKi +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __JFK_CORE__ +#ifndef __ORACLE__ +#include "common.h" +#endif + + +protocol jfki-core(I, R) +{ + role I { + fresh i, Ni: Nonce; + var Nr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ni, I, g(i) ); + recv_2( R, I, Nr, Ni, R, Gr, {Nr, Ni, Gr, g(i), I}sk(R) ); + send_3( I, R, Nr, Ni, {Nr, Ni, Gr, g(i), R}sk(I) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr: Nonce; + var Ni: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ni, I, Gi ); + send_2( R, I, Nr, Ni, R, g(r), {Nr, Ni, g(r), Gi, I}sk(R) ); + recv_3( I, R, Nr, Ni, {Nr, Ni, g(r), Gi, R}sk(I) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/jfki-core.spdl b/Vagrant Files/files/scyther/Protocols/IKE/jfki-core.spdl new file mode 100644 index 0000000..2517cbf --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/jfki-core.spdl @@ -0,0 +1,88 @@ +# 1 "jfki-core.cpp" +# 1 "<command-line>" +# 1 "jfki-core.cpp" +# 15 "jfki-core.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 60 "common.h" +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i), Ni, Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r), Ni, Nr) ); + + } + + +} +# 16 "jfki-core.cpp" 2 + + + +protocol jfki-core(I, R) +{ + role I { + fresh i, Ni: Nonce; + var Nr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ni, I, g(i) ); + recv_2( R, I, Nr, Ni, R, Gr, {Nr, Ni, Gr, g(i), I}sk(R) ); + send_3( I, R, Nr, Ni, {Nr, Ni, Gr, g(i), R}sk(I) ); + + + claim( I, SKR, KDF(h(Gr,i), Ni, Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr: Nonce; + var Ni: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ni, I, Gi ); + send_2( R, I, Nr, Ni, R, g(r), {Nr, Ni, g(r), Gi, I}sk(R) ); + recv_3( I, R, Nr, Ni, {Nr, Ni, g(r), Gi, R}sk(I) ); + + + claim( R, SKR, KDF(h(Gi,r), Ni, Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/jfki.cpp b/Vagrant Files/files/scyther/Protocols/IKE/jfki.cpp new file mode 100644 index 0000000..5b000f9 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/jfki.cpp @@ -0,0 +1,84 @@ +/** HEADDOC + * @protocol Just Fast Keying + * @reference Aiello et al., Just Fast Keying: Key Agreement In A Hostile + * Internet + * @description + * @variant Initiatior is identity protected +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __JFK__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, SAi, SAr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!O1( O, O, {I, SAi, {H(Ni), Nr, g(i), Gr, R, SAi}sk(I)}SKi ); + send_!O2( O, O, {I, SAi, {H(Ni), Nr, g(i), Gr, R, SAi}sk(I)}SKr ); + + // msg 4 + recv_!O3( O, O, {{H(Ni), Nr, g(i), Gr, I, SAi, SAr}sk(R), SAr}SKr ); + send_!O4( O, O, {{H(Ni), Nr, g(i), Gr, I, SAi, SAr}sk(R), SAr}SKi ); + + } +#undef Gi +#undef Gr +} + + +// Abstractions: no grpinfo, no MAC(ENC(M)), no ID_R', no IPi +protocol jfki(I, R) +{ + role I { + fresh i, Ni, SAi: Nonce; + var Nr, SAr: Nonce; + var Gr, TH: Ticket; + + send_1( I, R, H(Ni), g(i) ); + recv_2( R, I, H(Ni), Nr, Gr, R, {Gr}sk(R), TH ); + send_!3( I, R, Ni, Nr, g(i), Gr, TH, {I, SAi, {H(Ni), Nr, g(i), Gr, R, SAi}sk(I)}SKi ); + recv_!4( R, I, {{H(Ni), Nr, g(i), Gr, I, SAi, SAr}sk(R), SAr}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, SAr, HKr: Nonce; + var Ni, SAi: Nonce; + var Gi, HNi: Ticket; + + recv_1( I, R, HNi, Gi ); + send_2( R, I, HNi, Nr, g(r), R, {g(r)}sk(R), H(HKr, g(r), Nr, HNi) ); + // Note: if R can receive H(HKr, g(r), Nr, H(Ni)) then HNi=H(Ni) + recv_!3( I, R, Ni, Nr, Gi, g(r), H(HKr, g(r), Nr, H(Ni)), {I, SAi, {H(Ni), Nr, Gi, g(r), R, SAi}sk(I)}SKr ); + send_!4( R, I, {{H(Ni), Nr, Gi, g(r), I, SAi, SAr}sk(R), SAr}SKr ); + + /* SECURITY CLAIMS */ + claim( R, Secret, HKr ); + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/jfki.spdl b/Vagrant Files/files/scyther/Protocols/IKE/jfki.spdl new file mode 100644 index 0000000..d385543 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/jfki.spdl @@ -0,0 +1,118 @@ +# 1 "jfki.cpp" +# 1 "<command-line>" +# 1 "jfki.cpp" +# 15 "jfki.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 66 "common.h" +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i), H(Ni), Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r), H(Ni), Nr) ); + + } + + +} +# 16 "jfki.cpp" 2 + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, SAi, SAr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {I, SAi, {H(Ni), Nr, g(i), g(r), R, SAi}sk(I)}KDF(h(g(r),i), H(Ni), Nr) ); + send_!O2( O, O, {I, SAi, {H(Ni), Nr, g(i), g(r), R, SAi}sk(I)}KDF(h(g(i),r), H(Ni), Nr) ); + + + recv_!O3( O, O, {{H(Ni), Nr, g(i), g(r), I, SAi, SAr}sk(R), SAr}KDF(h(g(i),r), H(Ni), Nr) ); + send_!O4( O, O, {{H(Ni), Nr, g(i), g(r), I, SAi, SAr}sk(R), SAr}KDF(h(g(r),i), H(Ni), Nr) ); + + } + + +} + + + +protocol jfki(I, R) +{ + role I { + fresh i, Ni, SAi: Nonce; + var Nr, SAr: Nonce; + var Gr, TH: Ticket; + + send_1( I, R, H(Ni), g(i) ); + recv_2( R, I, H(Ni), Nr, Gr, R, {Gr}sk(R), TH ); + send_!3( I, R, Ni, Nr, g(i), Gr, TH, {I, SAi, {H(Ni), Nr, g(i), Gr, R, SAi}sk(I)}KDF(h(Gr,i), H(Ni), Nr) ); + recv_!4( R, I, {{H(Ni), Nr, g(i), Gr, I, SAi, SAr}sk(R), SAr}KDF(h(Gr,i), H(Ni), Nr) ); + + + claim( I, SKR, KDF(h(Gr,i), H(Ni), Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, SAr, HKr: Nonce; + var Ni, SAi: Nonce; + var Gi, HNi: Ticket; + + recv_1( I, R, HNi, Gi ); + send_2( R, I, HNi, Nr, g(r), R, {g(r)}sk(R), H(HKr, g(r), Nr, HNi) ); + + recv_!3( I, R, Ni, Nr, Gi, g(r), H(HKr, g(r), Nr, H(Ni)), {I, SAi, {H(Ni), Nr, Gi, g(r), R, SAi}sk(I)}KDF(h(Gi,r), H(Ni), Nr) ); + send_!4( R, I, {{H(Ni), Nr, Gi, g(r), I, SAi, SAr}sk(R), SAr}KDF(h(Gi,r), H(Ni), Nr) ); + + + claim( R, Secret, HKr ); + claim( R, SKR, KDF(h(Gi,r), H(Ni), Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/jfkr-core.cpp b/Vagrant Files/files/scyther/Protocols/IKE/jfkr-core.cpp new file mode 100644 index 0000000..500a8bb --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/jfkr-core.cpp @@ -0,0 +1,78 @@ +/** HEADDOC + * @protocol Just Fast Keying + * @reference Aiello et al., Just Fast Keying: Key Agreement In A Hostile + * Internet + * @description + * @variant Core cryptographic protocol of JFKr +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __JFK_CORE__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!O1( O, O, H(SKr, Nr, Ni, R) ); + send_!O2( O, O, H(SKi, Nr, Ni, R) ); + + // msg 4 + recv_!O3( O, O, H(SKi, Nr, Ni, I) ); + send_!O4( O, O, H(SKr, Nr, Ni, I) ); + + } +#undef Gi +#undef Gr +} + + +// Abstractions: same key for ENC, MAC +protocol jfkr-core(I, R) +{ + role I { + fresh i, Ni: Nonce; + var Nr, Gr: Ticket; + + send_1( I, R, Ni, g(i) ); + recv_!2( R, I, Nr, Ni, R, Gr, {Nr, Ni, Gr, g(i)}sk(R), H(SKi, Nr, Ni, R) ); + send_!3( I, R, Nr, Ni, I, {Nr, Ni, Gr, g(i)}sk(I), H(SKi, Nr, Ni, I) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr: Nonce; + var Ni, Gi: Ticket; + + recv_1( I, R, Ni, Gi ); + send_!2( R, I, Nr, Ni, R, g(r), {Nr, Ni, g(r), Gi}sk(R), H(SKr, Nr, Ni, R) ); + recv_!3( I, R, Nr, Ni, I, {Nr, Ni, g(r), Gi}sk(I), H(SKr, Nr, Ni, I) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/jfkr-core.spdl b/Vagrant Files/files/scyther/Protocols/IKE/jfkr-core.spdl new file mode 100644 index 0000000..adce573 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/jfkr-core.spdl @@ -0,0 +1,112 @@ +# 1 "jfkr-core.cpp" +# 1 "<command-line>" +# 1 "jfkr-core.cpp" +# 15 "jfkr-core.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 60 "common.h" +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i), Ni, Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r), Ni, Nr) ); + + } + + +} +# 16 "jfkr-core.cpp" 2 + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, H(KDF(h(g(i),r), Ni, Nr), Nr, Ni, R) ); + send_!O2( O, O, H(KDF(h(g(r),i), Ni, Nr), Nr, Ni, R) ); + + + recv_!O3( O, O, H(KDF(h(g(r),i), Ni, Nr), Nr, Ni, I) ); + send_!O4( O, O, H(KDF(h(g(i),r), Ni, Nr), Nr, Ni, I) ); + + } + + +} + + + +protocol jfkr-core(I, R) +{ + role I { + fresh i, Ni: Nonce; + var Nr, Gr: Ticket; + + send_1( I, R, Ni, g(i) ); + recv_!2( R, I, Nr, Ni, R, Gr, {Nr, Ni, Gr, g(i)}sk(R), H(KDF(h(Gr,i), Ni, Nr), Nr, Ni, R) ); + send_!3( I, R, Nr, Ni, I, {Nr, Ni, Gr, g(i)}sk(I), H(KDF(h(Gr,i), Ni, Nr), Nr, Ni, I) ); + + + claim( I, SKR, KDF(h(Gr,i), Ni, Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr: Nonce; + var Ni, Gi: Ticket; + + recv_1( I, R, Ni, Gi ); + send_!2( R, I, Nr, Ni, R, g(r), {Nr, Ni, g(r), Gi}sk(R), H(KDF(h(Gi,r), Ni, Nr), Nr, Ni, R) ); + recv_!3( I, R, Nr, Ni, I, {Nr, Ni, g(r), Gi}sk(I), H(KDF(h(Gi,r), Ni, Nr), Nr, Ni, I) ); + + + claim( R, SKR, KDF(h(Gi,r), Ni, Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/jfkr.cpp b/Vagrant Files/files/scyther/Protocols/IKE/jfkr.cpp new file mode 100644 index 0000000..fbe85d3 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/jfkr.cpp @@ -0,0 +1,83 @@ +/** HEADDOC + * @protocol Just Fast Keying + * @reference Aiello et al., Just Fast Keying: Key Agreement In A Hostile + * Internet + * @description + * @variant Responder is identity protected +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __JFK__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, SAi, SAr: Nonce; + var I, R: Agent; + + // msg 3 + recv_!O1( O, O, {I, SAi, {H(Ni), Nr, g(i), Gr}sk(I)}SKi ); + send_!O2( O, O, {I, SAi, {H(Ni), Nr, g(i), Gr}sk(I)}SKr ); + + // msg 4 + recv_!O3( O, O, {R, SAr, {Gr, Nr, g(i), H(Ni)}sk(R)}SKr ); + send_!O4( O, O, {R, SAr, {Gr, Nr, g(i), H(Ni)}sk(R)}SKi ); + + } +#undef Gi +#undef Gr +} + + +// Abstractions: no grpinfo, no MAC(ENC(M)), no ID_R', no IPi +protocol jfkr(I, R) +{ + role I { + fresh i, Ni, SAi: Nonce; + var Nr, SAr: Nonce; + var Gr, TH: Ticket; + + send_1( I, R, H(Ni), g(i) ); + recv_2( R, I, H(Ni), Nr, Gr, TH ); + send_!3( I, R, Ni, Nr, g(i), Gr, TH, {I, SAi, {H(Ni), Nr, g(i), Gr}sk(I)}SKi ); + recv_!4( R, I, {R, SAr, {Gr, Nr, g(i), H(Ni)}sk(R)}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, SAr, HKr: Nonce; + var Ni, SAi: Nonce; + var Gi, HNi: Ticket; + + recv_1( I, R, HNi, Gi ); + send_2( R, I, HNi, Nr, g(r), H(HKr, g(r), Nr, HNi) ); + recv_!3( I, R, Ni, Nr, Gi, g(r), H(HKr, g(r), Nr, H(Ni)), {I, SAi, {H(Ni), Nr, Gi, g(r)}sk(I)}SKr ); + send_!4( R, I, {R, SAr, {g(r), Nr, Gi, H(Ni)}sk(R)}SKr ); + + /* SECURITY CLAIMS */ + claim( R, Secret, HKr ); + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/jfkr.spdl b/Vagrant Files/files/scyther/Protocols/IKE/jfkr.spdl new file mode 100644 index 0000000..6e5e3e2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/jfkr.spdl @@ -0,0 +1,117 @@ +# 1 "jfkr.cpp" +# 1 "<command-line>" +# 1 "jfkr.cpp" +# 15 "jfkr.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 66 "common.h" +hashfunction H; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i), H(Ni), Nr) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r), H(Ni), Nr) ); + + } + + +} +# 16 "jfkr.cpp" 2 + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, SAi, SAr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {I, SAi, {H(Ni), Nr, g(i), g(r)}sk(I)}KDF(h(g(r),i), H(Ni), Nr) ); + send_!O2( O, O, {I, SAi, {H(Ni), Nr, g(i), g(r)}sk(I)}KDF(h(g(i),r), H(Ni), Nr) ); + + + recv_!O3( O, O, {R, SAr, {g(r), Nr, g(i), H(Ni)}sk(R)}KDF(h(g(i),r), H(Ni), Nr) ); + send_!O4( O, O, {R, SAr, {g(r), Nr, g(i), H(Ni)}sk(R)}KDF(h(g(r),i), H(Ni), Nr) ); + + } + + +} + + + +protocol jfkr(I, R) +{ + role I { + fresh i, Ni, SAi: Nonce; + var Nr, SAr: Nonce; + var Gr, TH: Ticket; + + send_1( I, R, H(Ni), g(i) ); + recv_2( R, I, H(Ni), Nr, Gr, TH ); + send_!3( I, R, Ni, Nr, g(i), Gr, TH, {I, SAi, {H(Ni), Nr, g(i), Gr}sk(I)}KDF(h(Gr,i), H(Ni), Nr) ); + recv_!4( R, I, {R, SAr, {Gr, Nr, g(i), H(Ni)}sk(R)}KDF(h(Gr,i), H(Ni), Nr) ); + + + claim( I, SKR, KDF(h(Gr,i), H(Ni), Nr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, SAr, HKr: Nonce; + var Ni, SAi: Nonce; + var Gi, HNi: Ticket; + + recv_1( I, R, HNi, Gi ); + send_2( R, I, HNi, Nr, g(r), H(HKr, g(r), Nr, HNi) ); + recv_!3( I, R, Ni, Nr, Gi, g(r), H(HKr, g(r), Nr, H(Ni)), {I, SAi, {H(Ni), Nr, Gi, g(r)}sk(I)}KDF(h(Gi,r), H(Ni), Nr) ); + send_!4( R, I, {R, SAr, {g(r), Nr, Gi, H(Ni)}sk(R)}KDF(h(Gi,r), H(Ni), Nr) ); + + + claim( R, Secret, HKr ); + claim( R, SKR, KDF(h(Gi,r), H(Ni), Nr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/make-mpa.py b/Vagrant Files/files/scyther/Protocols/IKE/make-mpa.py new file mode 100644 index 0000000..c75984d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/make-mpa.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +import os + +def getProtocolFiles(path=".",extension=""): + allfiles = os.listdir(path) + spfl = [] + for fn in allfiles: + if fn.endswith(extension): + spfl.append(fn) + return spfl + +def scanThis(fn,f,rewritelist,cnt): + + s = "" + mapping = [] + for lhs in rewritelist: + rhs = "%s%i" % (lhs,cnt) + mapping.append((lhs,rhs)) + + fp = open(fn,"r") + for rl in fp.xreadlines(): + l = rl + if f != None: + l = f(l) + for (lhs,rhs) in mapping: + l = l.replace(lhs,rhs) + s = s + l + fp.close() + return s + +def convertEm(f=None,path=".",rewritelist=[],newdir=".",oldext="",newext=None): + fl = getProtocolFiles(path=path,extension=oldext) + cnt = 1 + for fn in fl: + ffn = os.path.join(path,fn) + print "Processing",ffn + s = scanThis(ffn,f,rewritelist,cnt) + if newext == None: + fn2 = fn + else: + fn2 = fn.replace(oldext,newext) + ffn2 = os.path.join(newdir,fn2) + fp = open(ffn2,"w") + fp.write(s) + fp.close() + print "Produced",ffn2 + cnt = cnt+1 + +def preprocess(s): + s = s.replace("@oracle","@OracleA") + s = s.replace("@ora ", "@OracleB ") + s = s.replace("@ora(", "@OracleB(") + return s + +def main(): + convertEm(f=preprocess,rewritelist=["@OracleA","@executability","@OracleB"],path=".",newdir="mpa",oldext=".spdl") + print "Done." + +if __name__ == '__main__': + main() + + diff --git a/Vagrant Files/files/scyther/Protocols/IKE/mpa/README.txt b/Vagrant Files/files/scyther/Protocols/IKE/mpa/README.txt new file mode 100644 index 0000000..91e5266 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/mpa/README.txt @@ -0,0 +1,6 @@ +This directory is filled by the script + +`../make-mpa.py` + +It takes the `.spdl` files from the `..` directory and prepares them for +multi-protocol analysis. diff --git a/Vagrant Files/files/scyther/Protocols/IKE/oakley-a.cpp b/Vagrant Files/files/scyther/Protocols/IKE/oakley-a.cpp new file mode 100644 index 0000000..84db6b0 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/oakley-a.cpp @@ -0,0 +1,60 @@ +/** + * @protocol OAKLEY + * @reference RFC 2412, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description OAKLEY is related to STS and allows for shared key + * determination via authenticated Diffie-Hellman exchanges and + * provides perfect forward secrecy for the shared key. + * @variant Aggressive mode +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __OAKLEY__ +#ifndef __ORACLE__ +#include "common.h" +#endif + + +usertype String; +const list, algo: String; + +protocol oakley-a(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, g(i), list, I, R, Ni, {I, R, Ni, g(i), list}sk(I) ); + recv_2( R, I, Cr, Ci, Gr, algo, R, I, Nr, Ni, {R, I, Nr, Ni, g(i), Gr, algo}sk(R) ); + send_3( I, R, Ci, Cr, g(i), algo, I, R, Ni, Nr, {I, R, Ni, Nr, g(i), Gr, algo}sk(I) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, Gi, list, I, R, Ni, {I, R, Ni, Gi, list}sk(I) ); + send_2( R, I, Cr, Ci, g(r), algo, R, I, Nr, Ni, {R, I, Nr, Ni, Gi, g(r), algo}sk(R) ); + recv_3( I, R, Ci, Cr, Gi, algo, I, R, Ni, Nr, {I, R, Ni, Nr, Gi, g(r), algo}sk(I) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/oakley-a.spdl b/Vagrant Files/files/scyther/Protocols/IKE/oakley-a.spdl new file mode 100644 index 0000000..aa04c2e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/oakley-a.spdl @@ -0,0 +1,91 @@ +# 1 "oakley-a.cpp" +# 1 "<command-line>" +# 1 "oakley-a.cpp" +# 18 "oakley-a.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 141 "common.h" + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 19 "oakley-a.cpp" 2 + + + +usertype String; +const list, algo: String; + +protocol oakley-a(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, Ci, g(i), list, I, R, Ni, {I, R, Ni, g(i), list}sk(I) ); + recv_2( R, I, Cr, Ci, Gr, algo, R, I, Nr, Ni, {R, I, Nr, Ni, g(i), Gr, algo}sk(R) ); + send_3( I, R, Ci, Cr, g(i), algo, I, R, Ni, Nr, {I, R, Ni, Nr, g(i), Gr, algo}sk(I) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, Gi, list, I, R, Ni, {I, R, Ni, Gi, list}sk(I) ); + send_2( R, I, Cr, Ci, g(r), algo, R, I, Nr, Ni, {R, I, Nr, Ni, Gi, g(r), algo}sk(R) ); + recv_3( I, R, Ci, Cr, Gi, algo, I, R, Ni, Nr, {I, R, Ni, Nr, Gi, g(r), algo}sk(I) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/oakley-alt.cpp b/Vagrant Files/files/scyther/Protocols/IKE/oakley-alt.cpp new file mode 100644 index 0000000..5c4654f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/oakley-alt.cpp @@ -0,0 +1,63 @@ +/** HEADDOC + * @protocol OAKLEY + * @reference RFC 2412, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description OAKLEY is related to STS and allows for shared key + * determination via authenticated Diffie-Hellman exchanges and + * provides perfect forward secrecy for the shared key. + * @variant Alternative variant to prevent user identity disclosure +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __OAKLEY__ +#ifndef __ORACLE__ +#include "common.h" +#endif +#define AK prf(Ni,Nr) + + +usertype String; +const list, algo: String; + +protocol oakley-alt(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + // NOTE: pk(R) is sent in plain so that the recipient knows which decryption key to use + // In the specification, there is a distinction between the R in pk(R) and the encrypted R + send_1( I, R, Ci, g(i), list, pk(R), {I, R, Ni}pk(R) ); + recv_2( R, I, Cr, Ci, Gr, algo, {R, I, Nr}pk(I), prf(AK, R, I, Gr, g(i), algo) ); + send_3( I, R, Ci, Cr, prf(AK, I, R, g(i), Gr, algo) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, Gi, list, pk(R), {I, R, Ni}pk(R) ); + send_2( R, I, Cr, Ci, g(r), algo, {R, I, Nr}pk(I), prf(AK, R, I, g(r), Gi, algo) ); + recv_3( I, R, Ci, Cr, prf(AK, I, R, Gi, g(r), algo) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/oakley-alt.spdl b/Vagrant Files/files/scyther/Protocols/IKE/oakley-alt.spdl new file mode 100644 index 0000000..f94b355 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/oakley-alt.spdl @@ -0,0 +1,94 @@ +# 1 "oakley-alt.cpp" +# 1 "<command-line>" +# 1 "oakley-alt.cpp" +# 18 "oakley-alt.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 141 "common.h" + var Ci, Cr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 19 "oakley-alt.cpp" 2 + + + + +usertype String; +const list, algo: String; + +protocol oakley-alt(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + + + send_1( I, R, Ci, g(i), list, pk(R), {I, R, Ni}pk(R) ); + recv_2( R, I, Cr, Ci, Gr, algo, {R, I, Nr}pk(I), prf(prf(Ni,Nr), R, I, Gr, g(i), algo) ); + send_3( I, R, Ci, Cr, prf(prf(Ni,Nr), I, R, g(i), Gr, algo) ); + + + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, Ci, Gi, list, pk(R), {I, R, Ni}pk(R) ); + send_2( R, I, Cr, Ci, g(r), algo, {R, I, Nr}pk(I), prf(prf(Ni,Nr), R, I, g(r), Gi, algo) ); + recv_3( I, R, Ci, Cr, prf(prf(Ni,Nr), I, R, Gi, g(r), algo) ); + + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/oakley-c.cpp b/Vagrant Files/files/scyther/Protocols/IKE/oakley-c.cpp new file mode 100644 index 0000000..32e6a80 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/oakley-c.cpp @@ -0,0 +1,105 @@ +/** HEADDOC + * @protocol OAKLEY + * @reference RFC 2412, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description OAKLEY is related to STS and allows for shared key + * determination via authenticated Diffie-Hellman exchanges and + * provides perfect forward secrecy for the shared key. + * @variant Conservative mode with identity hiding +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __OAKLEY_CONSERVATIVE__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +#define Kpi prf(Zi) +#define Kpr prf(Zr) +#define Kir prf(Ni,Nr) + + +usertype String; +const OK, list, algo: String; + + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + // msg 5 + recv_!O1( O, O, {I, R, {Ni}pk(R)}Kpi ); + send_!O2( O, O, {I, R, {Ni}pk(R)}Kpr ); + + // msg 6 + recv_!O3( O, O, {{Nr, Ni}pk(I), R, I, prf(Kir, R, I, Gr, g(i), algo)}Kpr ); + send_!O4( O, O, {{Nr, Ni}pk(I), R, I, prf(Kir, R, I, Gr, g(i), algo)}Kpi ); + + // msg 7 + recv_!O5( O, O, {prf(Kir, I, R, g(i), Gr, algo)}Kpi ); + send_!O6( O, O, {prf(Kir, I, R, g(i), Gr, algo)}Kpr ); + + } +#undef Gi +#undef Gr +} + + +protocol oakley-c(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, OK ); + recv_2( R, I, Cr ); + send_3( I, R, Ci, Cr, g(i), list ); + recv_4( R, I, Cr, Ci, Gr, algo ); + send_!5( I, R, Ci, Cr, g(i), {I, R, {Ni}pk(R)}Kpi ); + recv_!6( R, I, Cr, Ci, {{Nr, Ni}pk(I), R, I, prf(Kir, R, I, Gr, g(i), algo)}Kpi ); + send_!7( I, R, Ci, Cr, {prf(Kir, I, R, g(i), Gr, algo)}Kpi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, Kpi ); + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, OK ); + send_2( R, I, Cr ); + recv_3( I, R, Ci, Cr, Gi, list ); + send_4( R, I, Cr, Ci, g(r), algo ); + recv_!5( I, R, Ci, Cr, Gi, {I, R, {Ni}pk(R)}Kpr ); + send_!6( R, I, Cr, Ci, {{Nr, Ni}pk(I), R, I, prf(Kir, R, I, g(r), Gi, algo)}Kpr ); + recv_!7( I, R, Ci, Cr, {prf(Kir, I, R, Gi, g(r), algo)}Kpr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, Kpr ); + + claim( R, SKR, SKr ); + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/oakley-c.spdl b/Vagrant Files/files/scyther/Protocols/IKE/oakley-c.spdl new file mode 100644 index 0000000..2585ef9 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/oakley-c.spdl @@ -0,0 +1,140 @@ +# 1 "oakley-c.cpp" +# 1 "<command-line>" +# 1 "oakley-c.cpp" +# 18 "oakley-c.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 144 "common.h" + var Ci, Cr: Nonce; + + + + + + recv_!SWAP1( SWAP, SWAP, KDF(Ni, Nr, h(g(r),i), Ci, Cr) ); + send_!SWAP2( SWAP, SWAP, KDF(Ni, Nr, h(g(i),r), Ci, Cr) ); + + } + + +} +# 19 "oakley-c.cpp" 2 + + + + + + + +usertype String; +const OK, list, algo: String; + + + + + + + +protocol @executability(O) { + + + role O { + var i, r, Ni, Nr, Ci, Cr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {I, R, {Ni}pk(R)}prf(h(g(r),i)) ); + send_!O2( O, O, {I, R, {Ni}pk(R)}prf(h(g(i),r)) ); + + + recv_!O3( O, O, {{Nr, Ni}pk(I), R, I, prf(prf(Ni,Nr), R, I, g(r), g(i), algo)}prf(h(g(i),r)) ); + send_!O4( O, O, {{Nr, Ni}pk(I), R, I, prf(prf(Ni,Nr), R, I, g(r), g(i), algo)}prf(h(g(r),i)) ); + + + recv_!O5( O, O, {prf(prf(Ni,Nr), I, R, g(i), g(r), algo)}prf(h(g(r),i)) ); + send_!O6( O, O, {prf(prf(Ni,Nr), I, R, g(i), g(r), algo)}prf(h(g(i),r)) ); + + } + + +} + + +protocol oakley-c(I, R) +{ + role I { + fresh i, Ni, Ci: Nonce; + var Nr, Cr: Nonce; + var Gr: Ticket; + + send_1( I, R, OK ); + recv_2( R, I, Cr ); + send_3( I, R, Ci, Cr, g(i), list ); + recv_4( R, I, Cr, Ci, Gr, algo ); + send_!5( I, R, Ci, Cr, g(i), {I, R, {Ni}pk(R)}prf(h(Gr,i)) ); + recv_!6( R, I, Cr, Ci, {{Nr, Ni}pk(I), R, I, prf(prf(Ni,Nr), R, I, Gr, g(i), algo)}prf(h(Gr,i)) ); + send_!7( I, R, Ci, Cr, {prf(prf(Ni,Nr), I, R, g(i), Gr, algo)}prf(h(Gr,i)) ); + + + claim( I, SKR, prf(h(Gr,i)) ); + claim( I, SKR, KDF(Ni, Nr, h(Gr,i), Ci, Cr) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr, Cr: Nonce; + var Ni, Ci: Nonce; + var Gi: Ticket; + + recv_1( I, R, OK ); + send_2( R, I, Cr ); + recv_3( I, R, Ci, Cr, Gi, list ); + send_4( R, I, Cr, Ci, g(r), algo ); + recv_!5( I, R, Ci, Cr, Gi, {I, R, {Ni}pk(R)}prf(h(Gi,r)) ); + send_!6( R, I, Cr, Ci, {{Nr, Ni}pk(I), R, I, prf(prf(Ni,Nr), R, I, g(r), Gi, algo)}prf(h(Gi,r)) ); + recv_!7( I, R, Ci, Cr, {prf(prf(Ni,Nr), I, R, Gi, g(r), algo)}prf(h(Gi,r)) ); + + + claim( R, SKR, prf(h(Gi,r)) ); + + claim( R, SKR, KDF(Ni, Nr, h(Gi,r), Ci, Cr) ); + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/pp.sh b/Vagrant Files/files/scyther/Protocols/IKE/pp.sh new file mode 100644 index 0000000..1ee7b6e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/pp.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +FILES="$*" +EXT="pp" +#OUT=. +OUT=pp-results + +if [ -n "$FILES" ]; then + for file in $FILES; + do + if [ "$file" = "*.$EXT.*" ]; then + echo "skipping $file" + else + echo "preprocessing $file" + cpp $file | sed -e '/^(\#.*)*$/d' > $OUT/${file%%.*}.$EXT.spdl + fi + done +else + printf "Usage: %s: file...\n" $(basename $0) >&2 + exit 1 +fi diff --git a/Vagrant Files/files/scyther/Protocols/IKE/scanner.py b/Vagrant Files/files/scyther/Protocols/IKE/scanner.py new file mode 100644 index 0000000..bc529ac --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/scanner.py @@ -0,0 +1,800 @@ +#!/usr/bin/env python + +import sys + +ALLPROTS = set() +ALLCLAIMS = set() # prot x role x claim +PREFIX = None # Required prefix +FFUNC = (lambda p: True) # Filter function + +def reset(): + + global ALLPROTS + global ALLCLAIMS + global PREFIX + global FFUNC + + ALLPROTS = set() + ALLCLAIMS = set() + PREFIX = None + FFUNC = (lambda p: True) + +def skipLine(l): + if len(l) == 0: + return True + + skippable = ["%","\\begin","\\end","Protocol"] + for skstr in skippable: + if l.startswith(skstr): + return True + + return False + +def stripRowEnd(l): + # Assume ends with \\, split by dtl + endstr = "\\\\" + if not l.endswith(endstr): + print "Error: some line does not end with \\\\" + print ">>%s<<" % (l) + sys.exit(-1) + + return l[:-len(endstr)] + +def splitStrip(l,sp): + + dtl = l.split(sp) + for i in range(0,len(dtl)): + dtl[i] = dtl[i].strip() + return dtl + +def roleClaim(dtl): + rcdt = dtl.split() + assert(rcdt[0].endswith(":")) + role = rcdt[0][:-1] + claim = rcdt[1] + return (role,claim[:20]) + +def scanAttackFile(fn): + + global ALLPROTS + + fp = open("gen-%s-mpaattacks.tex" % (fn),"r") + attackmap = {} + prot = None + role = None + claim = None + for rawline in fp.xreadlines(): + + l = rawline.strip() + + if skipLine(l): + continue + + l = stripRowEnd(l) + + dtl = splitStrip(l,"&") + + # New protocol + if len(dtl[0]) > 0: + prot = dtl[0] + + # New role + if len(dtl[1]) > 0: + (role,claim) = roleClaim(dtl[1]) + + # Claims list + # Assume starts with '[' and ends with ']' + assert(dtl[2].startswith("[")) + assert(dtl[2].endswith("]")) + attl = ((dtl[2])[1:-1]).split(",") + for i in range(0,len(attl)): + x = attl[i].strip() + assert(x.startswith("'")) + assert(x.endswith("'")) + attl[i] = x[1:-1] + + ak = (prot,role,claim) + if ak not in attackmap.keys(): + attackmap[ak] = set() + attackmap[ak].add(tuple(attl)) + + # Add to allprots set + ALLPROTS.add(prot) + for p in attl: + ALLPROTS.add(prot) + + fp.close() + + return attackmap + + +def shorten(prot): + """ + Shorten protocol name + """ + cutting = ["isoiec-","9798-"] + for ct in cutting: + if prot.startswith(ct): + prot = prot[len(ct):] + return prot.replace("-udkey","-ud") + + +def prettyclaim(cl): + """ + Rewrite if needed + """ + return cl.replace("Commit","Agreement") + + +def mpaTable(attackmap): + """ + construct table for MPA attacks + """ + counter = 1 + s = "" + + s += "\\begin{longtable}{|l|lll|l|}\n" + s += "\\hline\n" + for kk in sorted(ALLCLAIMS): + if kk not in attackmap.keys(): + continue + (prot,role,claim) = kk + + ats = str(attackmap[kk]) + sl = "%i & %s & %s & %s & %s \\\\ \n" % (counter,prot,role,claim,ats) + + s += sl + counter = counter + 1 + + s += "\\hline\n" + s += "\\end{longtable}\n" + + return s + + +def rotated(headl): + """ + Add rotated headers + """ + for i in range(0,len(headl)): + headl[i] = "\\begin{sideways} %s \\end{sideways}\n" % (headl[i]) + return " & ".join(headl) + + +def baseprot(prot): + return shorten(prot)[:5] + + +def mpaTable2(attackmap,tabtype="tabular",options=""): + """ + construct table for MPA attacks + + Second attempt + """ + + # To find the number of columns, we first need to find all protocols involved in two-protocol attacks + involved = set() + for kk in attackmap.keys(): + for atl in attackmap[kk]: + # convert tuple back to list + att = list(atl) + if len(att) == 1: + # This attack involves one *additional* protocol, so is a two-protocol attack + involved.add(att[0]) + colheads = sorted(involved) + attcols = "" + last = None + for hd in colheads: + prm = baseprot(hd) + if last == prm: + attcols += "@{\hspace{2mm}}c" + else: + last = prm + attcols += "|c" + + + #attcols = "c" * len(involved) + + counter = 1 + s = "" + + #s += "\\clearpage \n" + + s += "\\begin{%s}%s{|l|ll|%s|}\n" % (tabtype,options,attcols) + s += "\\hline\n" + s += rotated(["No","Prot","Claim"]) + for hd in colheads: + s += "& \\begin{sideways}%s\\end{sideways} " % (shorten(hd)) + s += "\\\\ \n" + + s += "\\hline\n" + last = None + for kk in sorted(ALLCLAIMS): + if kk not in attackmap.keys(): + continue + (prot,role,claim) = kk + + prm = baseprot(prot) + if last != prm: + last = prm + s += "\\hline\n" + + sl = "" + sl += "%i & %s & %s %s " % (counter,shorten(prot),role,claim) + for ch in colheads: + se = tuple([ch]) + if se in attackmap[kk]: + sl += "& $\\bullet$ " + else: + sl += "& $\\circ$ " + + sl += "\\\\ \n" + + s += sl + counter = counter + 1 + + s += "\\hline\n" + s += "\\end{%s}\n" % (tabtype) + + return s + + +def mpaTable3(attackmaps,tabtype="tabular",options=""): + """ + construct table for MPA attacks + + attmaps = sequence of (attackmap, symbol) + + Symbol of the first matching is displayed + + Second attempt + """ + + global FFUNC + # To find the number of columns, we first need to find all protocols involved in two-protocol attacks + # Also populate "allkeys" + involved = set() + allkeys = set() + for (attackmap,symbs) in attackmaps: + for kk in attackmap.keys(): + allkeys.add(kk) + for atl in attackmap[kk]: + # convert tuple back to list + att = list(atl) + if len(att) == 1: + # This attack involves one *additional* protocol, so is a two-protocol attack + if FFUNC: + if not FFUNC(att[0]): + continue + + involved.add(att[0]) + + colheads = sorted(involved) + attcols = "" + last = None + for hd in colheads: + prm = baseprot(hd) + if last == prm: + attcols += "@{\hspace{2mm}}c" + else: + last = prm + attcols += "|c" + + + #attcols = "c" * len(involved) + + counter = 1 + s = "" + + #s += "\\clearpage \n" + + s += "\\begin{%s}%s{|l|ll|%s|}\n" % (tabtype,options,attcols) + s += "\\hline\n" + s += rotated(["No","Prot","Claim"]) + for hd in colheads: + s += "& \\begin{sideways}%s\\end{sideways} " % (shorten(hd)) + s += "\\\\ \n" + + s += "\\hline\n" + last = None + for kk in sorted(ALLCLAIMS): + if kk not in attackmap.keys(): + continue + (prot,role,claim) = kk + + prm = baseprot(prot) + if last != prm: + last = prm + s += "\\hline\n" + + sl = "" + sl += "%i & %s & %s %s " % (counter,shorten(prot),role,prettyclaim(claim)) + for ch in colheads: + se = tuple([ch]) + sl += "& " + for (attackmap,symb) in attackmaps: + if kk in attackmap.keys(): + if se in attackmap[kk]: + sl += symb + break + + sl += "\\\\ \n" + + s += sl + counter = counter + 1 + + s += "\\hline\n" + s += "\\end{%s}\n" % (tabtype) + + return s + + +def scanClaimList(fn): + """ + Simply gather claims + """ + + global ALLPROTS + global ALLCLAIMS + global FFUNC + + fp = open("gen-%s-claims.txt" % (fn),"r") + + claimmap = {} + for rawline in fp.xreadlines(): + + l = rawline.strip() + + if skipLine(l): + continue + + dtl = splitStrip(l,"; ") + + filename = dtl[0] + prot = dtl[1] + if FFUNC: + if not FFUNC(prot): + continue + + label = dtl[2] + (role,claim) = roleClaim(dtl[3]) + + ALLCLAIMS.add((prot,role,claim)) + ALLPROTS.add(prot) + + fp.close() + + return claimmap + +def scanClaimFile(fn): + """ + Construct claimmap + + prot -> roles -> claims + """ + + global ALLPROTS + global ALLCLAIMS + global FFUNC + + fp = open("gen-%s-correctclaims.tex" % (fn),"r") + + claimmap = {} + for rawline in fp.xreadlines(): + + l = rawline.strip() + + if skipLine(l): + continue + + l = stripRowEnd(l) + + dtl = splitStrip(l,"&") + + prot = dtl[0] + if FFUNC: + if not FFUNC(prot): + continue + + if prot not in claimmap.keys(): + claimmap[prot] = {} + + cll = splitStrip(dtl[1],";") + + for dt in cll: + (role,claim) = roleClaim(dt) + + if role not in claimmap[prot].keys(): + claimmap[prot][role] = set() + + claimmap[prot][role].add(claim) + + ALLCLAIMS.add((prot,role,claim)) + + ALLPROTS.add(prot) + + fp.close() + + return claimmap + +def getRoleClaims(rcmap): + + rc = set() + for role in rcmap.keys(): + for claim in rcmap[role]: + rc.add((role,claim)) + + return rc + +def typeScanMatrix(cml,onlyChanged = False): + + global ALLPROTS + + """ + Scan for the influence of typing. + + Input: + + [(txt1,cm1),(txt2,cm2),...] + + """ + s = "" + + s += "\\begin{longtable}{|l|lll|%s|}\n" % ("c" * len(cml)) + s += "\\hline\n" + + s += "No & Prot & Role & Claim " + for (txt,cm) in cml: + s += "& %s " % (txt) + s += "\\\\\n" + s += "\\hline\n" + + goodverdict = "$\\circ$" + badverdict = "$\\bullet$" + + counter = 1 + for (prot,role,claim) in sorted(ALLCLAIMS): + # Header + sl = "%i & %s & %s & %s " % (counter,prot,role,claim) + alltrue = True + for (txt,cm) in cml: + verdict = badverdict + if prot in cm.keys(): + if role in cm[prot].keys(): + if claim in cm[prot][role]: + verdict = goodverdict + if verdict == badverdict: + alltrue = False + + sl += "& %s " % (verdict) + sl += "\\\\\n" + + if alltrue == True: + if onlyChanged == True: + continue + + s += sl + counter = counter + 1 + + s += "\\hline\n" + s += "\\end{longtable}\n" + return s + +def typeScanMatrix2(cml,onlyChanged = False,additive = False): + + global ALLPROTS + + """ + Scan for the influence of typing. + + Input: + + [(txt1,cm1),(txt2,cm2),...] + + """ + s = "" + + s += "\\begin{longtable}{|l|lll||c|}\n" + s += "\\hline\n" + + s += "No & Prot & Claim & Attacks" + s += "\\\\\n" + s += "\\hline\n" + s += "\\hline\n" + + goodverdict = "$\\circ$" + badverdict = "$\\bullet$" + + last = None + counter = 1 + for (prot,role,claim) in sorted(ALLCLAIMS): + if baseprot(prot) != last: + last = baseprot(prot) + s += "\\hline\n" + + # Header + sl = "%i & %s & %s %s " % (counter,prot,role,prettyclaim(claim)) + alltrue = True + res = "" + for (txt,cm) in cml: + verdict = badverdict + if prot in cm.keys(): + if role in cm[prot].keys(): + if claim in cm[prot][role]: + verdict = goodverdict + if verdict == badverdict: + alltrue = False + if additive: + res += txt + else: + res = txt + + sl += "& %s " % (res) + sl += "\\\\\n" + + if alltrue == True: + if onlyChanged == True: + continue + + s += sl + counter = counter + 1 + + s += "\\hline\n" + s += "\\end{longtable}\n" + return s + +def typeScanMatrix3(hd1,hd2,cml,f,onlyChanged = False,tabletype="longtable"): + + global ALLPROTS + + """ + Scan for the influence of typing. + + Input: + + f is given as input a sequence of Bool (attack = False) of length len(cml), should return string. + + """ + s = "" + + s += "\\begin{%s}{|l|ll||%s|}\n" % (tabletype,hd1) + s += "\\hline\n" + + s += rotated(["No","Protocol","Claim"]) + " & " + rotated(hd2) + s += "\\\\\n" + s += "\\hline\n" + s += "\\hline\n" + + goodverdict = "$\\circ$" + badverdict = "$\\bullet$" + + last = None + counter = 1 + for (prot,role,claim) in sorted(ALLCLAIMS): + if baseprot(prot) != last: + last = baseprot(prot) + s += "\\hline\n" + + # Header + sl = "%i & %s & %s %s " % (counter,prot,role,prettyclaim(claim)) + alltrue = True + res = "" + resl = [] + for cm in cml: + verdict = badverdict + if prot in cm.keys(): + if role in cm[prot].keys(): + if claim in cm[prot][role]: + verdict = goodverdict + if verdict == badverdict: + alltrue = False + resl.append(False) + else: + resl.append(True) + + sl += "& %s " % (f(resl)) + sl += "\\\\\n" + + if alltrue == True: + if onlyChanged == True: + continue + + s += sl + counter = counter + 1 + + s += "\\hline\n" + s += "\\end{%s}\n" % (tabletype) + return s + +def docWrapper(s,title=None,author=None): + + pref = "" + pref += "\\documentclass{article}\n" + pref += "\\usepackage{a4}\n" + pref += "\\usepackage{geometry}\n" + pref += "\\usepackage{longtable}\n" + pref += "\\usepackage{rotating}\n" + pref += "\\begin{document}\n" + if title or author: + if title: + pref += "\\title{%s}\n" % (title) + if author: + pref += "\\author{%s}\n" % (author) + pref += "\\maketitle\n" + post = "" + post += "\\end{document}\n" + + return pref + s + post + +def secWrapper(s,title,level=0): + """ + level : + + 0 section + 1 subsection + 2 subsub... + """ + pref = "\\" + "sub" * level + "section{" + title + "}\n\n" + post = "\n" + return pref + s + post + + +def sizeWrapper(s, width="!", height="!"): + + if (width != "!") or (height != "!"): + s = "\\resizebox{%s}{%s}{ \n%s}\n" % (width,height,s) + return s + + +def fileWrite(fn,s): + + fp = open("%s.tex" % (fn), "w") + fp.write(s) + fp.close() + + +def docWrite(fn,tex,author=None,title=None): + + fileWrite(fn, docWrapper(tex,author=author,title=title)) + + +def docMake(fn,tex,author=None,title=None): + + import commands + + docWrite(fn,tex,author,title) + cmd = "pdflatex %s" % (fn) + commands.getoutput(cmd) + +def f1(resl): + txtl = [] + for t in resl: + if t == True: + txtl.append(" ") + else: + txtl.append("$\\bullet$") + return " & ".join(txtl) + +def pb(tl,width): + nl = [] + for t in tl: + nl.append("\\parbox{%s}{%s}" % (width,t)) + return nl + +def makeReport(fn,includefiles=False): + scanClaimList(fn + "-aa-t") + + cISOaat = scanClaimFile(fn + "-aa-t") + cISOaab = scanClaimFile(fn + "-aa-b") + cISOaau = scanClaimFile(fn + "-aa-u") + cISOiut = scanClaimFile(fn + "-iu-t") + cISOiub = scanClaimFile(fn + "-iu-b") + cISOiuu = scanClaimFile(fn + "-iu-u") + cISOext = scanClaimFile(fn + "-ex-t") + cISOexb = scanClaimFile(fn + "-ex-b") + cISOexu = scanClaimFile(fn + "-ex-u") + + tex = "" + #tex += secWrapper(typeScanMatrix([("typed",cISOaat),("basic",cISOaab),("untyped",cISOaau)],onlyChanged = False),title="Normal mode (Alice-Alice communication allowed)") + #tex += secWrapper(typeScanMatrix([("typed",cISOiut),("basic",cISOiub),("untyped",cISOiuu)],onlyChanged = True),title="Disallow Alice-Alice initiators") + #tex += secWrapper(typeScanMatrix([("typed",cISOext),("basic",cISOexb),("untyped",cISOexu)],onlyChanged = True),title="Disallow Alice-Alice communications") + + orders = [cISOaab, + cISOaat, + cISOiub, + cISOiut] + + sectex = typeScanMatrix3("c|c|c|c",pb(["No type checks\\\\Alice-talks-to-Alice initators","Type checks\\\\Alice-talks-to-Alice initators","No type checks\\\\No Alice-talks-to-Alice initators","Type checks\\\\No Alice-talks-to-Alice initators"],"49mm"), orders,f1,onlyChanged = True) + + mpatex = sizeWrapper(mpaTable3([ + (scanAttackFile(fn + "-ex-t"),"$\\bullet$"), + (scanAttackFile(fn + "-aa-b"),"$\\circ$") + ]),width="\\textwidth") + + if includefiles == True: + fileWrite("../gen-att-" + fn,sectex) + fileWrite("../gen-mpa-" + fn,mpatex) + + tex += secWrapper(sectex,title="Attacks found") + tex += secWrapper(mpatex,title="MPA attacks") + docMake(fn,tex,author="Cas Cremers",title="test report %s" % (fn)) + + +def filterPrefix(prot): + """ + Returns true iff the protocol name is okay to be considered + """ + if PREFIX: + if not prot.startswith(PREFIX): + return False + return True + +def filterPrefixBD(prot): + """ + Returns true iff the protocol name is okay to be considered + """ + if PREFIX: + if not prot.startswith(PREFIX): + return False + if prot.endswith("-ud"): + return False + if prot.endswith("-udkey"): + return False + return True + + +def filterCombo(prot): + """ + Returns true iff the protocol name is okay to be considered + """ + if prot.find("-sig-child") >= 0: + return False + + return True + + +def filterISOsymmBD(prot): + """ + Returns true iff the protocol name is okay to be considered + """ + if prot.endswith("-ud"): + return False + if prot.endswith("-udkey"): + return False + + if prot.startswith("isoiec-9798-2"): + return True + if prot.startswith("isoiec-9798-4"): + return True + + return False + + + +if __name__ == "__main__": + + #reset() + #PREFIX = "isoiec-9798-2" + #makeReport(PREFIX) + + includefiles = True + + reset() + FFUNC = filterCombo + PREFIX = "ike1" + makeReport(PREFIX,includefiles=includefiles) + + reset() + FFUNC = filterCombo + PREFIX = "ike2" + makeReport(PREFIX,includefiles=includefiles) + + reset() + FFUNC = filterCombo + PREFIX = "ike0" + makeReport(PREFIX,includefiles=includefiles) + + + + + diff --git a/Vagrant Files/files/scyther/Protocols/IKE/skeme-basic.cpp b/Vagrant Files/files/scyther/Protocols/IKE/skeme-basic.cpp new file mode 100644 index 0000000..d9f58ab --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/skeme-basic.cpp @@ -0,0 +1,61 @@ +/** HEADDOC + * @protocol SKEME + * @reference Krawczyk, H., SKEME: A Versatile Secure Key Exchange Mechanism + * for Internet, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description SKEME is a set of protocols suitable for negotiation of + * services in a general networked environment. The main + * characteristics are forward secrecy, privacy and anonymity, + * and DoS protection. + * @variant Basic mode +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther + * Note: May use the same oracles as sts +**/ +#define __SKEME__ +#ifndef __ORACLE__ +#include "common.h" +#endif +#define Kir prf(Ni,Nr) + + +protocol skeme-basic(I, R) +{ + role I { + fresh i, Ni: Nonce; + var Nr: Nonce; + var Gr: Ticket; + + send_1( I, R, {I, Ni}pk(R), g(i) ); + recv_2( R, I, {Nr}pk(I), Gr, prf(Kir, g(i), Gr, R, I) ); + send_3( I, R, prf(Kir, Gr, g(i), I, R) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr: Nonce; + var Ni: Nonce; + var Gi: Ticket; + + recv_1( I, R, {I, Ni}pk(R), Gi ); + send_2( R, I, {Nr}pk(I), g(r), prf(Kir, Gi, g(r), R, I) ); + recv_3( I, R, prf(Kir, g(r), Gi, I, R) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/skeme-basic.spdl b/Vagrant Files/files/scyther/Protocols/IKE/skeme-basic.spdl new file mode 100644 index 0000000..8c53deb --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/skeme-basic.spdl @@ -0,0 +1,87 @@ +# 1 "skeme-basic.cpp" +# 1 "<command-line>" +# 1 "skeme-basic.cpp" +# 21 "skeme-basic.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i)) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r)) ); + + } + + +} +# 22 "skeme-basic.cpp" 2 + + + + +protocol skeme-basic(I, R) +{ + role I { + fresh i, Ni: Nonce; + var Nr: Nonce; + var Gr: Ticket; + + send_1( I, R, {I, Ni}pk(R), g(i) ); + recv_2( R, I, {Nr}pk(I), Gr, prf(prf(Ni,Nr), g(i), Gr, R, I) ); + send_3( I, R, prf(prf(Ni,Nr), Gr, g(i), I, R) ); + + + claim( I, SKR, KDF(h(Gr,i)) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r, Nr: Nonce; + var Ni: Nonce; + var Gi: Ticket; + + recv_1( I, R, {I, Ni}pk(R), Gi ); + send_2( R, I, {Nr}pk(I), g(r), prf(prf(Ni,Nr), Gi, g(r), R, I) ); + recv_3( I, R, prf(prf(Ni,Nr), g(r), Gi, I, R) ); + + + claim( R, SKR, KDF(h(Gi,r)) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/skeme-psk.cpp b/Vagrant Files/files/scyther/Protocols/IKE/skeme-psk.cpp new file mode 100644 index 0000000..355edc2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/skeme-psk.cpp @@ -0,0 +1,82 @@ +/** HEADDOC + * @protocol SKEME + * @reference Krawczyk, H., SKEME: A Versatile Secure Key Exchange Mechanism + * for Internet, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description SKEME is a set of protocols suitable for negotiation of + * services in a general networked environment. The main + * characteristics are forward secrecy, privacy and anonymity, + * and DoS protection. + * @variant Basic mode with pre-shared keys and correct application of DH +**/ + + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __SKEME__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling k(I,R) = k(R,I). + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, prf(k(R,I), Gi, g(r), R, I) ); + send_!O2( O, O, prf(k(I,R), Gi, g(r), R, I) ); + + // msg 3 + recv_!O3( O, O, prf(k(I,R), Gr, g(i), I, R) ); + send_!O4( O, O, prf(k(R,I), Gr, g(i), I, R) ); + + } +#undef Gi +#undef Gr +} + + +protocol skeme-psk(I, R) +{ + role I { + fresh i: Nonce; + var Gr: Ticket; + + send_1( I, R, g(i) ); + recv_!2( R, I, Gr, prf(k(I,R), g(i), Gr, R, I) ); + send_!3( I, R, prf(k(I,R), Gr, g(i), I, R) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r: Nonce; + var Gi: Ticket; + + recv_1( I, R, Gi ); + send_!2( R, I, g(r), prf(k(R,I), Gi, g(r), R, I) ); + recv_!3( I, R, prf(k(R,I), g(r), Gi, I, R) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/skeme-psk.spdl b/Vagrant Files/files/scyther/Protocols/IKE/skeme-psk.spdl new file mode 100644 index 0000000..e3e8796 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/skeme-psk.spdl @@ -0,0 +1,109 @@ +# 1 "skeme-psk.cpp" +# 1 "<command-line>" +# 1 "skeme-psk.cpp" +# 20 "skeme-psk.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i)) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r)) ); + + } + + +} +# 21 "skeme-psk.cpp" 2 + + + + + + + +protocol @executability(O) { + + + role O { + var i, r: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(k(R,I), g(i), g(r), R, I) ); + send_!O2( O, O, prf(k(I,R), g(i), g(r), R, I) ); + + + recv_!O3( O, O, prf(k(I,R), g(r), g(i), I, R) ); + send_!O4( O, O, prf(k(R,I), g(r), g(i), I, R) ); + + } + + +} + + +protocol skeme-psk(I, R) +{ + role I { + fresh i: Nonce; + var Gr: Ticket; + + send_1( I, R, g(i) ); + recv_!2( R, I, Gr, prf(k(I,R), g(i), Gr, R, I) ); + send_!3( I, R, prf(k(I,R), Gr, g(i), I, R) ); + + + claim( I, SKR, KDF(h(Gr,i)) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r: Nonce; + var Gi: Ticket; + + recv_1( I, R, Gi ); + send_!2( R, I, g(r), prf(k(R,I), Gi, g(r), R, I) ); + recv_!3( I, R, prf(k(R,I), g(r), Gi, I, R) ); + + + claim( R, SKR, KDF(h(Gi,r)) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/skeme-rekey.cpp b/Vagrant Files/files/scyther/Protocols/IKE/skeme-rekey.cpp new file mode 100644 index 0000000..a1915a2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/skeme-rekey.cpp @@ -0,0 +1,80 @@ +/** HEADDOC + * @protocol SKEME + * @reference Krawczyk, H., SKEME: A Versatile Secure Key Exchange Mechanism + * for Internet, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description SKEME is a set of protocols suitable for negotiation of + * services in a general networked environment. The main + * characteristics are forward secrecy, privacy and anonymity, + * and DoS protection. + * @variant Fast rekeying protocol +**/ + +/** MACRO DEFINITIONS + * Needs preprocessing by cpp before fed to scyther +**/ +#define __SKEME_REKEY__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling k(I,R) = k(R,I). + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var Ni, Nr: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, prf(k(R,I), Ni, Nr, R, I) ); + send_!O2( O, O, prf(k(I,R), Ni, Nr, R, I) ); + + // msg 3 + recv_!O3( O, O, prf(k(I,R), Nr, Ni, I, R) ); + send_!O4( O, O, prf(k(R,I), Nr, Ni, I, R) ); + + } +#undef Gi +#undef Gr +} + +protocol skeme-rekey(I, R) +{ + role I { + fresh Ni: Nonce; + var Nr: Nonce; + + send_1( I, R, Ni ); + recv_!2( R, I, Nr, prf(k(I,R), Ni, Nr, R, I) ); + send_!3( I, R, prf(k(I,R), Nr, Ni, I, R) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh Nr: Nonce; + var Ni: Nonce; + + recv_1( I, R, Ni ); + send_!2( R, I, Nr, prf(k(I,R), Ni, Nr, R, I) ); + recv_!3( I, R, prf(k(I,R), Nr, Ni, I, R) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/skeme-rekey.spdl b/Vagrant Files/files/scyther/Protocols/IKE/skeme-rekey.spdl new file mode 100644 index 0000000..acd0c50 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/skeme-rekey.spdl @@ -0,0 +1,111 @@ +# 1 "skeme-rekey.cpp" +# 1 "<command-line>" +# 1 "skeme-rekey.cpp" +# 19 "skeme-rekey.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 97 "common.h" +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 147 "common.h" + var I, R: Agent; + + + recv_!SWAP1( SWAP, SWAP, KDF(k(I,R),prf(k(I,R), Ni, Nr, R, I)) ); + send_!SWAP2( SWAP, SWAP, KDF(k(R,I),prf(k(R,I), Ni, Nr, R, I)) ); + + } + + +} +# 20 "skeme-rekey.cpp" 2 + + + + + + + +protocol @executability(O) { + + + role O { + var Ni, Nr: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, prf(k(R,I), Ni, Nr, R, I) ); + send_!O2( O, O, prf(k(I,R), Ni, Nr, R, I) ); + + + recv_!O3( O, O, prf(k(I,R), Nr, Ni, I, R) ); + send_!O4( O, O, prf(k(R,I), Nr, Ni, I, R) ); + + } + + +} + +protocol skeme-rekey(I, R) +{ + role I { + fresh Ni: Nonce; + var Nr: Nonce; + + send_1( I, R, Ni ); + recv_!2( R, I, Nr, prf(k(I,R), Ni, Nr, R, I) ); + send_!3( I, R, prf(k(I,R), Nr, Ni, I, R) ); + + + claim( I, SKR, KDF(k(I,R),prf(k(I,R), Ni, Nr, R, I)) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh Nr: Nonce; + var Ni: Nonce; + + recv_1( I, R, Ni ); + send_!2( R, I, Nr, prf(k(I,R), Ni, Nr, R, I) ); + recv_!3( I, R, prf(k(I,R), Nr, Ni, I, R) ); + + + claim( R, SKR, KDF(k(R,I),prf(k(R,I), Ni, Nr, R, I)) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/sts-mac.cpp b/Vagrant Files/files/scyther/Protocols/IKE/sts-mac.cpp new file mode 100644 index 0000000..9faaf4f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/sts-mac.cpp @@ -0,0 +1,78 @@ +/** HEADDOC + * @protocol Station-to-Station Protocol (STS) + * @reference Diffie W., van Oorschot P. C., and Wiener M. J., + * Authentication and authenticated key exchange, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description STS adds a diGital signaure to the exchanged messages to + * provide authentication for the Diffie-Hellman protocol. In + * addition, the shared secret is used to provide further + * assurances. + * @variant Variant using MACs +**/ + +#define __STS__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r: Nonce; + + // msg 2 + recv_!O1( O, O, MAC(Zr, g(r), Gi) ); + send_!O2( O, O, MAC(Zi, g(r), Gi) ); + + // msg 3 + recv_!O3( O, O, MAC(Zi, Gi, g(r)) ); + send_!O4( O, O, MAC(Zr, Gi, g(r)) ); + + } +#undef Gi +#undef Gr +} + +// It is not specified how the session key is derived from the ephemeral DH +// secret Z; we use KDF(Z). +protocol sts-mac(I, R) +{ + role I { + fresh i: Nonce; + var Gr: Ticket; + + send_1( I, R, g(i) ); + recv_!2( R, I, Gr, {Gr, g(i)}sk(R), MAC(Zi, Gr, g(i)) ); + send_!3( I, R, {g(i), Gr}sk(I), MAC(Zi, g(i), Gr) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r: Nonce; + var Gi: Ticket; + + recv_1( I, R, Gi ); + send_!2( R, I, Gi, {g(r), Gi}sk(R), MAC(Zr, g(r), Gi) ); + recv_!3( I, R, {Gi, g(r)}sk(I), MAC(Zr, Gi, g(r)) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/sts-mac.spdl b/Vagrant Files/files/scyther/Protocols/IKE/sts-mac.spdl new file mode 100644 index 0000000..09c583b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/sts-mac.spdl @@ -0,0 +1,112 @@ +# 1 "sts-mac.cpp" +# 1 "<command-line>" +# 1 "sts-mac.cpp" +# 16 "sts-mac.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 94 "common.h" +hashfunction MAC; + + +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i)) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r)) ); + + } + + +} +# 17 "sts-mac.cpp" 2 + + + + + + + +protocol @executability(O) { + + + role O { + var i, r: Nonce; + + + recv_!O1( O, O, MAC(h(g(i),r), g(r), g(i)) ); + send_!O2( O, O, MAC(h(g(r),i), g(r), g(i)) ); + + + recv_!O3( O, O, MAC(h(g(r),i), g(i), g(r)) ); + send_!O4( O, O, MAC(h(g(i),r), g(i), g(r)) ); + + } + + +} + + + +protocol sts-mac(I, R) +{ + role I { + fresh i: Nonce; + var Gr: Ticket; + + send_1( I, R, g(i) ); + recv_!2( R, I, Gr, {Gr, g(i)}sk(R), MAC(h(Gr,i), Gr, g(i)) ); + send_!3( I, R, {g(i), Gr}sk(I), MAC(h(Gr,i), g(i), Gr) ); + + + claim( I, SKR, KDF(h(Gr,i)) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r: Nonce; + var Gi: Ticket; + + recv_1( I, R, Gi ); + send_!2( R, I, Gi, {g(r), Gi}sk(R), MAC(h(Gi,r), g(r), Gi) ); + recv_!3( I, R, {Gi, g(r)}sk(I), MAC(h(Gi,r), Gi, g(r)) ); + + + claim( R, SKR, KDF(h(Gi,r)) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/sts-main.cpp b/Vagrant Files/files/scyther/Protocols/IKE/sts-main.cpp new file mode 100644 index 0000000..b95d306 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/sts-main.cpp @@ -0,0 +1,79 @@ +/** HEADDOC + * @protocol Station-to-Station Protocol (STS) + * @reference Diffie W., van Oorschot P. C., and Wiener M. J., + * Authentication and authenticated key exchange, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description STS adds a digital signaure to the exchanged messages to + * provide authentication for the Diffie-Hellman protocol. In + * addition, the shared secret is used to provide further + * assurances. +**/ + +#define __STS__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +/** + * This role serves as an "oracle" to ensure the executability of the + * protocol by taking care of the problems that arise from our way of + * modelling Diffie-Hellman keys. + */ +protocol @executability(O) { +#define Gi g(i) +#define Gr g(r) + role O { + var i, r: Nonce; + var I, R: Agent; + + // msg 2 + recv_!O1( O, O, {{g(r), Gi}sk(R)}SKr ); + send_!O2( O, O, {{g(r), Gi}sk(R)}SKi ); + + // msg 3 + recv_!O3( O, O, {{g(i), Gr}sk(I)}SKi ); + send_!O4( O, O, {{g(i), Gr}sk(I)}SKr ); + + } +#undef Gi +#undef Gr +} + + +// It is not specified how the session key is derived from the ephemeral DH +// secret Z; we use KDF(Z). +protocol sts-main(I, R) +{ + role I { + fresh i: Nonce; + var Gr: Ticket; + + send_1( I, R, g(i) ); + recv_!2( R, I, Gr, {{Gr, g(i)}sk(R)}SKi ); + send_!3( I, R, {{g(i), Gr}sk(I)}SKi ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r: Nonce; + var Gi: Ticket; + + recv_1( I, R, Gi ); + send_!2( R, I, g(r), {{g(r), Gi}sk(R)}SKr ); + recv_!3( I, R, {{Gi, g(r)}sk(I)}SKr ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/sts-main.spdl b/Vagrant Files/files/scyther/Protocols/IKE/sts-main.spdl new file mode 100644 index 0000000..4cfb76c --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/sts-main.spdl @@ -0,0 +1,114 @@ +# 1 "sts-main.cpp" +# 1 "<command-line>" +# 1 "sts-main.cpp" +# 15 "sts-main.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 94 "common.h" +hashfunction MAC; + + +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i)) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r)) ); + + } + + +} +# 16 "sts-main.cpp" 2 + + + + + + + +protocol @executability(O) { + + + role O { + var i, r: Nonce; + var I, R: Agent; + + + recv_!O1( O, O, {{g(r), g(i)}sk(R)}KDF(h(g(i),r)) ); + send_!O2( O, O, {{g(r), g(i)}sk(R)}KDF(h(g(r),i)) ); + + + recv_!O3( O, O, {{g(i), g(r)}sk(I)}KDF(h(g(r),i)) ); + send_!O4( O, O, {{g(i), g(r)}sk(I)}KDF(h(g(i),r)) ); + + } + + +} + + + + +protocol sts-main(I, R) +{ + role I { + fresh i: Nonce; + var Gr: Ticket; + + send_1( I, R, g(i) ); + recv_!2( R, I, Gr, {{Gr, g(i)}sk(R)}KDF(h(Gr,i)) ); + send_!3( I, R, {{g(i), Gr}sk(I)}KDF(h(Gr,i)) ); + + + claim( I, SKR, KDF(h(Gr,i)) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r: Nonce; + var Gi: Ticket; + + recv_1( I, R, Gi ); + send_!2( R, I, g(r), {{g(r), Gi}sk(R)}KDF(h(Gi,r)) ); + recv_!3( I, R, {{Gi, g(r)}sk(I)}KDF(h(Gi,r)) ); + + + claim( R, SKR, KDF(h(Gi,r)) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/sts-modified.cpp b/Vagrant Files/files/scyther/Protocols/IKE/sts-modified.cpp new file mode 100644 index 0000000..458a042 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/sts-modified.cpp @@ -0,0 +1,55 @@ +/** HEADDOC + * @protocol Station-to-Station Protocol (STS) + * @reference Diffie W., van Oorschot P. C., and Wiener M. J., + * Authentication and authenticated key exchange, + * Boyd C. and Mathuria A., Protocols for Authentication and + * Key Agreement + * @description STS adds a diGital signaure to the exchanged messages to + * provide authentication for the Diffie-Hellman protocol. In + * addition, the shared secret is used to provide further + * assurances. + * @variant Variant proposed by Boyd et al to prevent unknown key-share + * attacks. +**/ + +#define __STS__ +#ifndef __ORACLE__ +#include "common.h" +#endif + +// It is not specified how the session key is derived from the ephemeral DH +// secret Z; we use KDF(Z). +protocol sts-modified(I, R) +{ + role I { + fresh i: Nonce; + var Gr: Ticket; + + send_1( I, R, g(i) ); + recv_2( R, I, Gr, {Gr, g(i), I}sk(R) ); + send_3( I, R, {g(i), Gr, R}sk(I) ); + + /* SECURITY CLAIMS */ + claim( I, SKR, SKi ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r: Nonce; + var Gi: Ticket; + + recv_1( I, R, Gi ); + send_2( R, I, g(r), {g(r), Gi, I}sk(R) ); + recv_3( I, R, {Gi, g(r), R}sk(I) ); + + /* SECURITY CLAIMS */ + claim( R, SKR, SKr ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} \ No newline at end of file diff --git a/Vagrant Files/files/scyther/Protocols/IKE/sts-modified.spdl b/Vagrant Files/files/scyther/Protocols/IKE/sts-modified.spdl new file mode 100644 index 0000000..660d068 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/sts-modified.spdl @@ -0,0 +1,88 @@ +# 1 "sts-modified.cpp" +# 1 "<command-line>" +# 1 "sts-modified.cpp" +# 17 "sts-modified.cpp" +# 1 "common.h" 1 + + + + + hashfunction prf, KDF; + + + + + + +hashfunction g, h; +# 94 "common.h" +hashfunction MAC; + + +protocol @oracle (DH, SWAP) { + + + + + + + + role DH { + var i, r: Nonce; + + recv_!DH1( DH, DH, h(g(r),i) ); + send_!DH2( DH, DH, h(g(i),r) ); + } + + + + + role SWAP { + var i, r, Ni, Nr: Nonce; +# 150 "common.h" + recv_!SWAP1( SWAP, SWAP, KDF(h(g(r),i)) ); + send_!SWAP2( SWAP, SWAP, KDF(h(g(i),r)) ); + + } + + +} +# 18 "sts-modified.cpp" 2 + + + + +protocol sts-modified(I, R) +{ + role I { + fresh i: Nonce; + var Gr: Ticket; + + send_1( I, R, g(i) ); + recv_2( R, I, Gr, {Gr, g(i), I}sk(R) ); + send_3( I, R, {g(i), Gr, R}sk(I) ); + + + claim( I, SKR, KDF(h(Gr,i)) ); + + claim( I, Alive ); + claim( I, Weakagree ); + + } + + role R { + fresh r: Nonce; + var Gi: Ticket; + + recv_1( I, R, Gi ); + send_2( R, I, g(r), {g(r), Gi, I}sk(R) ); + recv_3( I, R, {Gi, g(r), R}sk(I) ); + + + claim( R, SKR, KDF(h(Gi,r)) ); + + claim( R, Alive ); + claim( R, Weakagree ); + + } +} diff --git a/Vagrant Files/files/scyther/Protocols/IKE/verify.sh b/Vagrant Files/files/scyther/Protocols/IKE/verify.sh new file mode 100644 index 0000000..44f2b61 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/verify.sh @@ -0,0 +1,149 @@ +############################################################################# +# +# NAME +# verify - batch protocol verifier script for scyther +# +# SYNOPSIS +# ./verify.sh [option]... [file]... +# +# DESCRIPTION +# Verify protocol specifications using scyther. +# +# OPTIONS +# +# -d Debug mode [false] +# -e Execution environment [cluster] +# -h Help +# -i Skip attack patterns of the form Alice talking to Alice +# -l lower bound of claims to check [1] +# -m Adversary-compromise model [ext] +# -o Output directory (attack graphs) [./graphs/] +# -r number of runs [6] +# -t timeout in s +# -u upper bound of claims to check [1] +# +# EXAMPLE +# ./verify.sh -m br -o . *.spdl +# +############################################################################# + + +#!/bin/bash + +# Default values +CLAIM[0]=1 +CLAIM[1]=1 +DEBUG=false +ENV='cluster' +FILES="*.spdl" +INITUNIQUE= +MODEL='ext' +OUTDIR='./graphs' +RUNS='-r 6' +SCYTHER='../scyther/Scyther/scyther-linux' +TIMEOUT= + +# Adversary-compromise models +# EXT +MODELS[0]= +# INT +MODELS[1]='--LKRothers 1' +# CA +MODELS[2]='--LKRactor 1' +# AF +MODELS[3]='--LKRafter 1' +# AFC +MODELS[4]='--LKRaftercorrect 1' +# BR +MODELS[5]='--LKRothers 1 --SKR 1 --SKRinfer' # (inferred session keys) +MODELS[6]='--LKRothers 1 --SKR 1' +# CKw +MODELS[7]='--LKRothers 1 --LKRactor 1 --LKRaftercorrect 1 --SKR 1 --SKRinfer --SSR 1' +MODELS[8]='--LKRothers 1 --LKRactor 1 --LKRaftercorrect 1 --SKR 1 --SSR 1' +# CK +MODELS[9]='--LKRothers 1 --LKRafter 1 --LKRaftercorrect 1 --SKR 1 --SKRinfer --SSR 1' +MODELS[10]='--LKRothers 1 --LKRafter 1 --LKRaftercorrect 1 --SKR 1 --SSR 1' +# eCK-1 +MODELS[11]='--LKRothers 1 --SKR 1 --SKRinfer --RNR 1' +MODELS[12]='--LKRothers 1 --SKR 1 --RNR 1' +# eCK-2 +MODELS[13]='--LKRothers 1 --LKRactor 1 --LKRaftercorrect 1 --SKR 1 --SKRinfer' +MODELS[14]='--LKRothers 1 --LKRactor 1 --LKRaftercorrect 1 --SKR 1' + + +# Parse command line arguments +while getopts “de:hil:m:o:r:t:u:” FLAG; +do + case $FLAG in + d) DEBUG=true;; + e) ENV=$OPTARG;; + i) INITUNIQUE='--init-unique';; + l) CLAIM[0]=$OPTARG;; + m) MODEL=$OPTARG;; + o) OUTDIR=$OPTARG;; + r) RUNS="-r $OPTARG";; + t) TIMEOUT="-T $OPTARG";; + u) CLAIM[1]=$OPTARG;; + h|?) + printf "Usage: %s: [-l num][-u num][-d][-e [cluster|remote|local]][-h][-m model][-o value][-r num][-t sec]file[...]\n" $(basename $0) >&2 + exit 1;; + esac +done +shift $(($OPTIND - 1)) + +# Remaining arguments treated as specification files +if [ -n "$*" ]; then + FILES="$*" + # mkdir -p "$OUTDIR$TSTAMP" +fi + + +# Parse model identifiers +mflags= +case $MODEL in + int) mflags=${MODELS[1]};; + ca) mflags=${MODELS[2]};; + af) mflags=${MODELS[3]};; + afc) mflags=${MODELS[4]};; + bri) mflags=${MODELS[5]};; + br) mflags=${MODELS[6]};; + ckwi) mflags=${MODELS[7]};; + ckw) mflags=${MODELS[8]};; + cki) mflags=${MODELS[9]};; + ck) mflags=${MODELS[10]};; + eck1i) mflags=${MODELS[11]};; + eck1) mflags=${MODELS[12]};; + eck2i) mflags=${MODELS[13]};; + eck2) mflags=${MODELS[14]};; +esac + + +# Verify +for file in $FILES; +do + EXT=`echo "$file" | sed 's/^.*\.//'` + if [ "$EXT" == 'spdl' ]; then + # Extract protocol name + tmp=`basename $file .spdl` + p=`basename $tmp .pp` + + # Execute scyther for selected models and claim + for (( c=${CLAIM[0]}; c<=${CLAIM[1]}; c++ )); + do + init="$SCYTHER $TIMEOUT --force-regular $INITUNIQUE $RUNS $mflags $file -d -o $OUTDIR/${p}_adv-${MODEL}_I$c.dot --filter=$p,I$c" + resp="$SCYTHER $TIMEOUT --force-regular $INITUNIQUE $RUNS $mflags $file -d -o $OUTDIR/${p}_adv-${MODEL}_R$c.dot --filter=$p,R$c" + if $DEBUG; then + echo $init + echo $resp + elif [ $ENV = "cluster" ]; then + bsub -W 08:00 -R "rusage[mem=4096]" $init + bsub -W 08:00 -R "rusage[mem=4096]" $resp + else # $ENV = local + time $init + time $resp + fi + done + else + printf "WARNING: %s could not be processed." $file + fi +done diff --git a/Vagrant Files/files/scyther/Protocols/IKE/verify_all.sh b/Vagrant Files/files/scyther/Protocols/IKE/verify_all.sh new file mode 100644 index 0000000..0cad2f6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/IKE/verify_all.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +if [ -n "$*" ]; then + FILES="$*" + ./verify.sh -i -r 4 -l 1 -u 3 -e remote $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m int $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m ca $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m afc $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m af $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m br $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m bri $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m ckw $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m ckwi $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m ck $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m cki $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m eck1 $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m eck1i $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m eck2 $FILES + ./verify.sh -i -r 4 -l 1 -u 3 -e remote -m eck2i $FILES +fi diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/Makefile b/Vagrant Files/files/scyther/Protocols/ISO-9798/Makefile new file mode 100644 index 0000000..e0a1179 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/Makefile @@ -0,0 +1,16 @@ + +outputs= isoiec-9798-3-6-1.spdl isoiec-9798-3-6-2.spdl \ + isoiec-9798-3-7-1.spdl isoiec-9798-3-7-2.spdl + +all: $(outputs) + +isoiec-9798-3-6-%.spdl: isoiec-9798-3-6-%.cpp isoiec-9798-3-6.template + cpp -C -P $< >$@ + +isoiec-9798-3-7-%.spdl: isoiec-9798-3-7-%.cpp isoiec-9798-3-7.template + cpp -C -P $< >$@ + +clean: + \rm -f $(outputs) + + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/iso25-tag.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/iso25-tag.spdl new file mode 100644 index 0000000..a97164b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/iso25-tag.spdl @@ -0,0 +1,78 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * ttp + * four-pass + * mutual + * + * Modeling notes: + * - The use of TNb in message 4, as specified by the ISO standard, is + * different from other models, in which it was TNa. + */ +usertype SessionKey; +usertype Tag; + +const t1,t2a,t2b,t3,t4,t5: Tag; + +protocol isoiec-9798-2-5(A,B,P) +{ + role A + { + fresh TVPa: Nonce; + var T: Ticket; + fresh TNa: Nonce; + var TNb: Nonce; + var Kab: SessionKey; + fresh Text1,Text5,Text6: Ticket; + var Text3,Text4,Text7,Text8: Ticket; + + send_1(A,P, TVPa, B, Text1); + recv_2(P,A, Text4, { t2a, TVPa, Kab, B, Text3 }k(A,P), T ); + claim(A,Running,B,Kab,Text5); + send_3(A,B, Text6, T, { t3, TNa, B, Text5 }Kab ); + recv_4(B,A, Text8, { t4, TNb, A, Text7 }Kab ); + + claim(A,Commit,B,Kab,Text5,Text7); + claim(A,Secret,Kab); + claim(A,Secret,Text5); + claim(A,Secret,Text7); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var TNp: Nonce; + var TNa: Nonce; + fresh TNb: Nonce; + var Kab: SessionKey; + fresh Text7,Text8: Ticket; + var Text2,Text5,Text6: Ticket; + + recv_3(A,B, Text6, { t2b, TNp, Kab, A, Text2 }k(B,P), { + t3, TNa, B, Text5 }Kab ); + claim(B,Running,A,Kab,Text5,Text7); + send_4(B,A, Text8, { t4, TNb, A, Text7 }Kab ); + + claim(B,Commit,A,Kab,Text5); + claim(B,Secret,Kab); + claim(B,Secret,Text5); + claim(B,Secret,Text7); + claim(B,Alive); + claim(B,Weakagree); + } + role P + { + var TVPa: Nonce; + fresh TNp: Nonce; + fresh Kab: SessionKey; + fresh Text2,Text3,Text4: Ticket; + var Text1: Ticket; + + recv_1(A,P, TVPa, B, Text1); + send_2(P,A, Text4, { t2a, TVPa, Kab, B, Text3 }k(A,P), + { t2b, TNp, Kab, A, Text2 }k(B,P) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/iso26-tag.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/iso26-tag.spdl new file mode 100644 index 0000000..ced5d02 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/iso26-tag.spdl @@ -0,0 +1,95 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * ttp + * five-pass + * mutual + * + * MPA Attack reported by Mathuria: + * - Type flaw MPA when in parallel with Abadi-Needham protocol. + * + */ +usertype Tag; + +const t1,t2,t3,t4,t5: Tag; + +protocol isoiec-9798-2-6-tag(A,B,P) +{ + role A + { + var Rb: Nonce; + fresh Ra,Rpa: Nonce; + var Kab: SessionKey; + var T: Ticket; + fresh Text2,Text6,Text7: Ticket; + var Text1,Text4,Text5,Text8,Text9: Ticket; + + recv_1(B,A, Rb, Text1); + send_2(A,P, Ra, Rb, B, Text2); + recv_3(P,A, Text5, {t1, Ra,Kab,B,Text4}k(A,P), T ); + claim(A,Running,B,Kab,Text6); + send_4(A,B, Text7, T, {t3,Rpa,Rb,Text6}Kab ); + recv_5(B,A, Text9, {t4,Rb,Rpa,Text8}Kab ); + + claim(A,Commit,B,Kab,Text6,Text8); + claim(A,Secret,Kab); + claim(A,Secret,Text6); + claim(A,Secret,Text8); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + fresh Rb: Nonce; + var Rpa: Nonce; + var Kab: SessionKey; + fresh Text1,Text8,Text9: Ticket; + var Text3,Text6,Text7: Ticket; + + send_1(B,A, Rb, Text1); + recv_4(A,B, Text7, {t2,Rb,Kab,A,Text3}k(B,P), {t3,Rpa,Rb,Text6}Kab ); + claim(B,Running,A,Kab,Text6,Text8); + send_5(B,A, Text9, {t4,Rb,Rpa,Text8}Kab ); + + claim(B,Commit,A,Kab,Text6); + claim(B,Secret,Kab); + claim(B,Secret,Text6); + claim(B,Secret,Text8); + claim(B,Alive); + claim(B,Weakagree); + } + role P + { + var Ra, Rb: Nonce; + fresh Kab: SessionKey; + fresh Text3,Text4,Text5: Ticket; + var Text2: Ticket; + + recv_2(A,P, Ra, Rb, B, Text2); + send_3(P,A, Text5, {t1,Ra,Kab,B,Text4}k(A,P), + {t2,Rb,Kab,A,Text3}k(B,P) ); + } +} + +protocol @keysymm26(A,B,P) +{ + role A + { + var TVPN: Nonce; + var Kab: SessionKey; + var Text: Ticket; + var Tag: Ticket; + + recv_!1(B,A, { Tag,TVPN, Kab, B, Text }k(P,A) ); + send_!2(A,B, { Tag,TVPN, Kab, B, Text }k(A,P) ); + } + role B + { + } + role P + { + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-1-udkey.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-1-udkey.spdl new file mode 100644 index 0000000..e1f8be6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-1-udkey.spdl @@ -0,0 +1,35 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * one-pass + * unilateral + * + * Note: the identity B may be ommitted, if + * (a) the environment disallows such attacks, or + * (b) a unidirectional key is used + */ +protocol isoiec-9798-2-1-udkey(A,B) +{ + role A + { + fresh TNA: Nonce; + fresh Text1,Text2: Ticket; + + claim(A,Running,B,TNA,Text1); + send_1(A,B, Text2, { TNA, Text1 }k(A,B) ); + } + role B + { + var TNA: Nonce; + var Text1,Text2: Ticket; + + recv_1(A,B, Text2, { TNA, Text1 }k(A,B) ); + + claim(B,Commit,A,TNA,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-1.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-1.spdl new file mode 100644 index 0000000..0d47be3 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-1.spdl @@ -0,0 +1,55 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * one-pass + * unilateral + * + * Note: the identity B may be ommitted, if + * (a) the environment disallows such attacks, or + * (b) a unidirectional key is used + */ +protocol @keysymm-21(A,B) +{ + role A + { + var T: Nonce; + var Text: Ticket; + + recv_!1(B,A, { T, A, Text }k(A,B) ); + send_!2(A,B, { T, A, Text }k(B,A) ); + } + role B + { + var T: Nonce; + var Text: Ticket; + + recv_!3(A,B, { T, B, Text }k(A,B) ); + send_!4(B,A, { T, B, Text }k(B,A) ); + } +} + +protocol isoiec-9798-2-1(A,B) +{ + role A + { + fresh TNA: Nonce; + fresh Text1,Text2: Ticket; + + claim(A,Running,B,TNA,Text1); + send_1(A,B, Text2, { TNA, B, Text1 }k(A,B) ); + } + role B + { + var TNA: Nonce; + var Text1,Text2: Ticket; + + recv_1(A,B, Text2, { TNA, B, Text1 }k(A,B) ); + + claim(B,Commit,A,TNA,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-2-udkey.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-2-udkey.spdl new file mode 100644 index 0000000..314aa8e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-2-udkey.spdl @@ -0,0 +1,40 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * two-pass + * unilateral + * + * Note: the identity A may be ommitted, if + * (a) the environment disallows such attacks, or + * (b) a unidirectional key is used + * + */ +protocol isoiec-9798-2-2-udkey(A,B) +{ + role A + { + var RB: Nonce; + var Text1: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, RB,Text1 ); + claim(A,Running,B,RB,Text2); + send_2(A,B, Text3, { RB, Text2 }k(B,A) ); + } + role B + { + fresh RB: Nonce; + fresh Text1: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, RB,Text1 ); + recv_2(A,B, Text3, { RB, Text2 }k(B,A) ); + + claim(B,Commit,A,RB,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-2.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-2.spdl new file mode 100644 index 0000000..fc1ae68 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-2.spdl @@ -0,0 +1,59 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * two-pass + * unilateral + * + * Note: the identity A may be ommitted, if + * (a) the environment disallows such attacks, or + * (b) a unidirectional key is used + */ +protocol @keysymm-22(A,B) +{ + role A + { + var T: Nonce; + var Text: Ticket; + + recv_!1(B,A, { T, A, Text }k(A,B) ); + send_!2(A,B, { T, A, Text }k(B,A) ); + } + role B + { + var T: Nonce; + var Text: Ticket; + + recv_!3(A,B, { T, B, Text }k(A,B) ); + send_!4(B,A, { T, B, Text }k(B,A) ); + } +} + +protocol isoiec-9798-2-2(A,B) +{ + role A + { + var RB: Nonce; + var Text1: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, RB,Text1 ); + claim(A,Running,B,RB,Text2); + send_2(A,B, Text3, { RB, B, Text2 }k(B,A) ); + } + role B + { + fresh RB: Nonce; + fresh Text1: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, RB,Text1 ); + recv_2(A,B, Text3, { RB, B, Text2 }k(B,A) ); + + claim(B,Commit,A,RB,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-3-udkey.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-3-udkey.spdl new file mode 100644 index 0000000..9fddf69 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-3-udkey.spdl @@ -0,0 +1,49 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * two-pass + * mutual + * + * Note: the identity inside the encryption may be ommitted, if + * (a) the environment disallows such attacks, or + * (b) a unidirectional key is used + * + * In case (b), modeled here, the second key is reversed. + * + */ +protocol isoiec-9798-2-3-udkey(A,B) +{ + role A + { + fresh TNA: Nonce; + var TNB: Nonce; + fresh Text1,Text2: Ticket; + var Text3,Text4: Ticket; + + claim(A,Running,B,TNA,Text1); + send_1(A,B, Text2, { TNA, Text1 }k(A,B) ); + recv_2(B,A, Text4, { TNB, Text3 }k(B,A) ); + + claim(A,Commit,B,TNB,Text3); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var TNA: Nonce; + fresh TNB: Nonce; + var Text1,Text2: Ticket; + fresh Text3,Text4: Ticket; + + recv_1(A,B, Text2, { TNA, Text1 }k(A,B) ); + claim(B,Running,A,TNB,Text3); + send_2(B,A, Text4, { TNB, Text3 }k(B,A) ); + + claim(B,Commit,A,TNA,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-3.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-3.spdl new file mode 100644 index 0000000..6f2f86b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-3.spdl @@ -0,0 +1,67 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * two-pass + * mutual + * + * Note: the identity inside the encryption may be ommitted, if + * (a) the environment disallows such attacks, or + * (b) a unidirectional key is used + * + */ +protocol @keysymm-23(A,B) +{ + role A + { + var T: Nonce; + var Text: Ticket; + + recv_!1(B,A, { T, A, Text }k(A,B) ); + send_!2(A,B, { T, A, Text }k(B,A) ); + } + role B + { + var T: Nonce; + var Text: Ticket; + + recv_!3(A,B, { T, B, Text }k(A,B) ); + send_!4(B,A, { T, B, Text }k(B,A) ); + } +} + +protocol isoiec-9798-2-3(A,B) +{ + role A + { + fresh TNA: Nonce; + var TNB: Nonce; + fresh Text1,Text2: Ticket; + var Text3,Text4: Ticket; + + claim(A,Running,B,TNA,Text1); + send_1(A,B, Text2, { TNA, B, Text1 }k(A,B) ); + recv_2(B,A, Text4, { TNB, A, Text3 }k(A,B) ); + + claim(A,Commit,B,TNB,Text3); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var TNA: Nonce; + fresh TNB: Nonce; + var Text1,Text2: Ticket; + fresh Text3,Text4: Ticket; + + recv_1(A,B, Text2, { TNA, B, Text1 }k(A,B) ); + claim(B,Running,A,TNB,Text3); + send_2(B,A, Text4, { TNB, A, Text3 }k(A,B) ); + + claim(B,Commit,A,TNA,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-4-udkey.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-4-udkey.spdl new file mode 100644 index 0000000..28694de --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-4-udkey.spdl @@ -0,0 +1,50 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * three-pass + * mutual + * + * Note: the identity inside the encryption may be ommitted, if + * (a) the environment disallows such attacks, or + * (b) a unidirectional key is used + * + * In case (b), modeled here, the second key is reversed. + */ +protocol isoiec-9798-2-4-udkey(A,B) +{ + role A + { + var RB: Nonce; + fresh RA: Nonce; + var Text1,Text4,Text5: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, RB,Text1 ); + claim(A,Running,B,RA,RB,Text2); + send_2(A,B, Text3, { RA, RB, Text2 }k(A,B) ); + recv_3(B,A, Text5, { RB, RA, Text4 }k(B,A) ); + + claim(A,Commit,B,RA,RB,Text2,Text4); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + fresh RB: Nonce; + var RA: Nonce; + fresh Text1,Text4,Text5: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, RB,Text1 ); + recv_2(A,B, Text3, { RA, RB, Text2 }k(A,B) ); + claim(B,Running,A,RA,RB,Text2,Text4); + send_3(B,A, Text5, { RB, RA, Text4 }k(B,A) ); + + claim(B,Commit,A,RA,RB,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-4.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-4.spdl new file mode 100644 index 0000000..5d709c0 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-4.spdl @@ -0,0 +1,88 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * three-pass + * mutual + * + * Note: the identity inside the encryption may be ommitted, if + * (a) the environment disallows such attacks, or + * (b) a unidirectional key is used + */ +protocol @keysymm-24a(A,B) +{ + role A + { + var T1,T2: Nonce; + var Text: Ticket; + + recv_!1(B,A, { T1, T2, A, Text }k(A,B) ); + send_!2(A,B, { T1, T2, A, Text }k(B,A) ); + } + role B + { + var T1,T2: Nonce; + var Text: Ticket; + + recv_!3(A,B, { T1, T2, B, Text }k(A,B) ); + send_!4(B,A, { T1, T2, B, Text }k(B,A) ); + } +} + +protocol @keysymm-24b(A,B) +{ + role A + { + var T1,T2: Nonce; + var Text: Ticket; + + recv_!1(B,A, { T1, T2, Text }k(A,B) ); + send_!2(A,B, { T1, T2, Text }k(B,A) ); + } + role B + { + var T1,T2: Nonce; + var Text: Ticket; + + recv_!3(A,B, { T1, T2, Text }k(A,B) ); + send_!4(B,A, { T1, T2, Text }k(B,A) ); + } +} + +protocol isoiec-9798-2-4(A,B) +{ + role A + { + var RB: Nonce; + fresh RA: Nonce; + var Text1,Text4,Text5: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, RB,Text1 ); + claim(A,Running,B,RA,RB,Text2); + send_2(A,B, Text3, { RA, RB, B, Text2 }k(A,B) ); + recv_3(B,A, Text5, { RB, RA, Text4 }k(A,B) ); + + claim(A,Commit,B,RA,RB,Text2,Text4); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + fresh RB: Nonce; + var RA: Nonce; + fresh Text1,Text4,Text5: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, RB,Text1 ); + recv_2(A,B, Text3, { RA, RB, B, Text2 }k(A,B) ); + claim(B,Running,A,RA,RB,Text2,Text4); + send_3(B,A, Text5, { RB, RA, Text4 }k(A,B) ); + + claim(B,Commit,A,RA,RB,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-5.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-5.spdl new file mode 100644 index 0000000..7a98c0d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-5.spdl @@ -0,0 +1,93 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * ttp + * four-pass + * mutual + * + * Modeling notes: + * - The use of TNb in message 4, as specified by the ISO standard, is + * different from other models, in which it was TNa. + */ +usertype SessionKey; + +protocol isoiec-9798-2-5(A,B,P) +{ + role A + { + fresh TVPa: Nonce; + var T: Ticket; + fresh TNa: Nonce; + var TNb: Nonce; + var Kab: SessionKey; + fresh Text1,Text5,Text6: Ticket; + var Text3,Text4,Text7,Text8: Ticket; + + send_1(A,P, TVPa, B, Text1); + recv_2(P,A, Text4, { TVPa, Kab, B, Text3 }k(A,P), T ); + claim(A,Running,B,Kab,Text5); + send_3(A,B, Text6, T, { TNa, B, Text5 }Kab ); + recv_4(B,A, Text8, { TNb, A, Text7 }Kab ); + + claim(A,Commit,B,Kab,Text5,Text7); + claim(A,Secret,Kab); + claim(A,Secret,Text5); + claim(A,Secret,Text7); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var TNp: Nonce; + var TNa: Nonce; + fresh TNb: Nonce; + var Kab: SessionKey; + fresh Text7,Text8: Ticket; + var Text2,Text5,Text6: Ticket; + + recv_3(A,B, Text6, { TNp, Kab, A, Text2 }k(B,P), { TNa, B, Text5 }Kab ); + claim(B,Running,A,Kab,Text5,Text7); + send_4(B,A, Text8, { TNb, A, Text7 }Kab ); + + claim(B,Commit,A,Kab,Text5); + claim(B,Secret,Kab); + claim(B,Secret,Text5); + claim(B,Secret,Text7); + claim(B,Alive); + claim(B,Weakagree); + } + role P + { + var TVPa: Nonce; + fresh TNp: Nonce; + fresh Kab: SessionKey; + fresh Text2,Text3,Text4: Ticket; + var Text1: Ticket; + + recv_1(A,P, TVPa, B, Text1); + send_2(P,A, Text4, { TVPa, Kab, B, Text3 }k(A,P), + { TNp, Kab, A, Text2 }k(B,P) ); + } +} + +protocol @keysymm25(A,B,P) +{ + role A + { + var TVPN: Nonce; + var Kab: SessionKey; + var Text: Ticket; + + recv_!1(B,A, { TVPN, Kab, B, Text }k(P,A) ); + send_!2(A,B, { TVPN, Kab, B, Text }k(A,P) ); + } + role B + { + } + role P + { + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-6.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-6.spdl new file mode 100644 index 0000000..703885b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-2-6.spdl @@ -0,0 +1,90 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * symmetric + * ttp + * five-pass + * mutual + * + * MPA Attack reported by Mathuria: + * - Type flaw MPA when in parallel with Abadi-Needham protocol. + * + */ +protocol isoiec-9798-2-6(A,B,P) +{ + role A + { + var Rb: Nonce; + fresh Ra,Rpa: Nonce; + var Kab: SessionKey; + var T: Ticket; + fresh Text2,Text6,Text7: Ticket; + var Text1,Text4,Text5,Text8,Text9: Ticket; + + recv_1(B,A, Rb, Text1); + send_2(A,P, Ra, Rb, B, Text2); + recv_3(P,A, Text5, {Ra,Kab,B,Text4}k(A,P), T ); + claim(A,Running,B,Kab,Text6); + send_4(A,B, Text7, T, {Rpa,Rb,Text6}Kab ); + recv_5(B,A, Text9, {Rb,Rpa,Text8}Kab ); + + claim(A,Commit,B,Kab,Text6,Text8); + claim(A,Secret,Kab); + claim(A,Secret,Text6); + claim(A,Secret,Text8); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + fresh Rb: Nonce; + var Rpa: Nonce; + var Kab: SessionKey; + fresh Text1,Text8,Text9: Ticket; + var Text3,Text6,Text7: Ticket; + + send_1(B,A, Rb, Text1); + recv_4(A,B, Text7, {Rb,Kab,A,Text3}k(B,P), {Rpa,Rb,Text6}Kab ); + claim(B,Running,A,Kab,Text6,Text8); + send_5(B,A, Text9, {Rb,Rpa,Text8}Kab ); + + claim(B,Commit,A,Kab,Text6); + claim(B,Secret,Kab); + claim(B,Secret,Text6); + claim(B,Secret,Text8); + claim(B,Alive); + claim(B,Weakagree); + } + role P + { + var Ra, Rb: Nonce; + fresh Kab: SessionKey; + fresh Text3,Text4,Text5: Ticket; + var Text2: Ticket; + + recv_2(A,P, Ra, Rb, B, Text2); + send_3(P,A, Text5, {Ra,Kab,B,Text4}k(A,P), + {Rb,Kab,A,Text3}k(B,P) ); + } +} + +protocol @keysymm26(A,B,P) +{ + role A + { + var TVPN: Nonce; + var Kab: SessionKey; + var Text: Ticket; + + recv_!1(B,A, { TVPN, Kab, B, Text }k(P,A) ); + send_!2(A,B, { TVPN, Kab, B, Text }k(A,P) ); + } + role B + { + } + role P + { + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-1.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-1.spdl new file mode 100644 index 0000000..42b5667 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-1.spdl @@ -0,0 +1,33 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * signature + * one-pass + * unilateral + */ +const Cert: Function; + +protocol isoiec-9798-3-1(A,B) +{ + role A + { + fresh TNA: Nonce; + fresh Text1,Text2: Ticket; + + claim(A,Running,B,TNA,Text1); + send_1(A,B, Cert(A),TNA,B,Text2, { TNA, B, Text1 }sk(A) ); + } + role B + { + var TNA: Nonce; + var Text1,Text2: Ticket; + + recv_1(A,B, Cert(A),TNA,B,Text2, { TNA, B, Text1 }sk(A) ); + + claim(B,Commit,A,TNA,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-2.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-2.spdl new file mode 100644 index 0000000..97f5c68 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-2.spdl @@ -0,0 +1,39 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * signature + * two-pass + * unilateral + */ +const Cert: Function; + +protocol isoiec-9798-3-2(A,B) +{ + role A + { + var Rb: Nonce; + fresh Ra: Nonce; + var Text1: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, Rb,Text1 ); + claim(A,Running,B,Ra,Rb,Text2); + send_2(A,B, Cert(A),Ra,Rb,B,Text3, { Ra, Rb, B, Text2 }sk(A) ); + } + role B + { + fresh Rb: Nonce; + var Ra: Nonce; + fresh Text1: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, Rb,Text1 ); + recv_2(A,B, Cert(A),Ra,Rb,B,Text3, { Ra, Rb, B, Text2 }sk(A) ); + + claim(B,Commit,A,Ra,Rb,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-3.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-3.spdl new file mode 100644 index 0000000..ca1d944 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-3.spdl @@ -0,0 +1,44 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * signature + * two-pass + * mutual + */ +const Cert: Function; + +protocol isoiec-9798-3-3(A,B) +{ + role A + { + fresh TNA: Nonce; + var TNB: Nonce; + fresh Text1,Text2: Ticket; + var Text3,Text4: Ticket; + + claim(A,Running,B,TNA,Text1); + send_1(A,B, Cert(A), TNA, B,Text2, { TNA, B, Text1 }sk(A) ); + recv_2(B,A, Cert(B), TNB, A,Text4, { TNB, A, Text3 }sk(B) ); + + claim(A,Commit,B,TNB,Text3); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var TNA: Nonce; + fresh TNB: Nonce; + var Text1,Text2: Ticket; + fresh Text3,Text4: Ticket; + + recv_1(A,B, Cert(A), TNA, B,Text2, { TNA, B, Text1 }sk(A) ); + claim(B,Running,A,TNB,Text3); + send_2(B,A, Cert(B), TNB, A,Text4, { TNB, A, Text3 }sk(B) ); + + claim(B,Commit,A,TNA,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-4.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-4.spdl new file mode 100644 index 0000000..f8bfbbc --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-4.spdl @@ -0,0 +1,46 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * signature + * three-pass + * mutual + */ +const Cert: Function; + +protocol isoiec-9798-3-4(A,B) +{ + role A + { + var RB: Nonce; + fresh RA: Nonce; + var Text1,Text4,Text5: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, RB,Text1 ); + claim(A,Running,B,RA,RB,Text2); + send_2(A,B, Cert(B), RA,RB,B,Text3, { RA, RB, B, Text2 }sk(A) ); + recv_3(B,A, Cert(A), RB,RA,A,Text5, { RB, RA, A, Text4 }sk(B) ); + + claim(A,Commit,B,RA,RB,Text2,Text4); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + fresh RB: Nonce; + var RA: Nonce; + fresh Text1,Text4,Text5: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, RB,Text1 ); + recv_2(A,B, Cert(B), RA,RB,B,Text3, { RA, RB, B, Text2 }sk(A) ); + claim(B,Running,A,RA,RB,Text2,Text4); + send_3(B,A, Cert(A), RB,RA,A,Text5, { RB, RA, A, Text4 }sk(B) ); + + claim(B,Commit,A,RA,RB,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-5.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-5.spdl new file mode 100644 index 0000000..237e56f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-5.spdl @@ -0,0 +1,49 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * signature + * two-pass + * mutual + * parallel + */ +const Cert: Function; + +protocol isoiec-9798-3-5(A,B) +{ + role A + { + fresh RA: Nonce; + var RB: Nonce; + fresh Text1,Text3,Text4: Ticket; + var Text2,Text5,Text6: Ticket; + + send_1(A,B, Cert(A), RA,Text1 ); + recv_2(B,A, Cert(B), RB,Text2 ); + recv_3(B,A, RB,RA,A,Text6, { RB, RA, A, Text5 }sk(B) ); + claim(A,Running,B,RA,RB,Text3,Text5); + send_4(A,B, RA,RB,B,Text4, { RA, RB, B, Text3 }sk(A) ); + + claim(A,Commit,B,RA,RB,Text5); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var RA: Nonce; + fresh RB: Nonce; + var Text1,Text3,Text4: Ticket; + fresh Text2,Text5,Text6: Ticket; + + recv_1(A,B, Cert(A), RA,Text1 ); + send_2(B,A, Cert(B), RB,Text2 ); + claim(B,Running,A,RA,RB,Text5); + send_3(B,A, RB,RA,A,Text6, { RB, RA, A, Text5 }sk(B) ); + recv_4(A,B, RA,RB,B,Text4, { RA, RB, B, Text3 }sk(A) ); + + claim(B,Commit,A,RA,RB,Text3,Text5); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-1.cpp b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-1.cpp new file mode 100644 index 0000000..fb5b93b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-1.cpp @@ -0,0 +1,12 @@ +#define NAME isoiec-9798-3-6-1 +#define IA A +#define IB B +#define ResA A,pk(A) +#define ResB B,pk(B) +#define TokenAB Text9,ResA,{Rb,ResA,Text5}sk(T),{Rb,Ra,B,A,Text8}sk(A) +#define TokenBA Ra,Rb,Text3,{B,Ra,Rb,A,Text2}sk(B) +#define TokenTA ResA,ResB,{Rpa,ResB,Text6}sk(T),{Rb,ResA,Text5}sk(T) + +#include "isoiec-9798-3-6.template" + + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-1.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-1.spdl new file mode 100644 index 0000000..51545a6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-1.spdl @@ -0,0 +1,69 @@ + + +/* + * Modeled from ISO standard + * + * signature + * ttp + * five-pass + * mutual + * + * A initiates and also communicates with T + * + * parameters: + * + * NAME + * IA + * IB + * ResA + * ResB + * TokenAB + * TokenBA (although identical in both cases) + * TokenTA + * + */ +protocol isoiec-9798-3-6-1(A,B,T) +{ + role A + { + fresh Ra,Rpa: Nonce; + fresh Text1,Text4,Text8,Text9: Ticket; + var Rb: Nonce; + var Text2,Text3; + var Text5,Text6,Text7: Ticket; + + send_1(A,B, Ra,A,Text1); + recv_2(B,A, B,Ra,Rb,Text3,{B,Ra,Rb,A,Text2}sk(B)); + send_3(A,T, Rpa,Rb,A,B,Text4); + recv_4(T,A, Text7,A,pk(A),B,pk(B),{Rpa,B,pk(B),Text6}sk(T),{Rb,A,pk(A),Text5}sk(T)); + claim(A,Running,B,Ra,Rb,Text8); + send_5(A,B, Text9,A,pk(A),{Rb,A,pk(A),Text5}sk(T),{Rb,Ra,B,A,Text8}sk(A)); + + claim(A,Commit,B,Ra,Rb,Text2); + claim(A,Alive); + } + role B + { + var Ra,Rpa: Nonce; + var Text1,Text5,Text8,Text9: Ticket; + fresh Text2,Text3,Text4: Ticket; + fresh Rb: Nonce; + + recv_1(A,B, Ra,A,Text1); + claim(B,Running,A,Ra,Rb,Text2); + send_2(B,A, B,Ra,Rb,Text3,{B,Ra,Rb,A,Text2}sk(B)); + recv_5(A,B, Text9,A,pk(A),{Rb,A,pk(A),Text5}sk(T),{Rb,Ra,B,A,Text8}sk(A)); + + claim(B,Commit,A,Ra,Rb,Text8); + claim(B,Alive); + } + role T + { + var Rpa, Rb: Nonce; + var Text4: Ticket; + fresh Text5,Text6,Text7: Ticket; + + recv_3(A,T, Rpa,Rb,A,B,Text4); + send_4(T,A, Text7,A,pk(A),B,pk(B),{Rpa,B,pk(B),Text6}sk(T),{Rb,A,pk(A),Text5}sk(T)); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-2.cpp b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-2.cpp new file mode 100644 index 0000000..d40ca51 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-2.cpp @@ -0,0 +1,12 @@ +#define NAME isoiec-9798-3-6-2 +#define IA A +#define IB B +#define ResA A,pk(A) +#define ResB B,pk(B) +#define TokenAB Rpa,Text9,TokenTA,{Rb,Ra,B,A,Text8}sk(A) +#define TokenBA Ra,Rb,Text3,{B,Ra,Rb,A,Text2}sk(B) +#define TokenTA ResA,ResB,{Rpa,Rb,ResA,ResB,Text5}sk(T) + +#include "isoiec-9798-3-6.template" + + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-2.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-2.spdl new file mode 100644 index 0000000..3debbc7 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6-2.spdl @@ -0,0 +1,69 @@ + + +/* + * Modeled from ISO standard + * + * signature + * ttp + * five-pass + * mutual + * + * A initiates and also communicates with T + * + * parameters: + * + * NAME + * IA + * IB + * ResA + * ResB + * TokenAB + * TokenBA (although identical in both cases) + * TokenTA + * + */ +protocol isoiec-9798-3-6-2(A,B,T) +{ + role A + { + fresh Ra,Rpa: Nonce; + fresh Text1,Text4,Text8,Text9: Ticket; + var Rb: Nonce; + var Text2,Text3; + var Text5,Text6,Text7: Ticket; + + send_1(A,B, Ra,A,Text1); + recv_2(B,A, B,Ra,Rb,Text3,{B,Ra,Rb,A,Text2}sk(B)); + send_3(A,T, Rpa,Rb,A,B,Text4); + recv_4(T,A, Text7,A,pk(A),B,pk(B),{Rpa,Rb,A,pk(A),B,pk(B),Text5}sk(T)); + claim(A,Running,B,Ra,Rb,Text8); + send_5(A,B, Rpa,Text9,A,pk(A),B,pk(B),{Rpa,Rb,A,pk(A),B,pk(B),Text5}sk(T),{Rb,Ra,B,A,Text8}sk(A)); + + claim(A,Commit,B,Ra,Rb,Text2); + claim(A,Alive); + } + role B + { + var Ra,Rpa: Nonce; + var Text1,Text5,Text8,Text9: Ticket; + fresh Text2,Text3,Text4: Ticket; + fresh Rb: Nonce; + + recv_1(A,B, Ra,A,Text1); + claim(B,Running,A,Ra,Rb,Text2); + send_2(B,A, B,Ra,Rb,Text3,{B,Ra,Rb,A,Text2}sk(B)); + recv_5(A,B, Rpa,Text9,A,pk(A),B,pk(B),{Rpa,Rb,A,pk(A),B,pk(B),Text5}sk(T),{Rb,Ra,B,A,Text8}sk(A)); + + claim(B,Commit,A,Ra,Rb,Text8); + claim(B,Alive); + } + role T + { + var Rpa, Rb: Nonce; + var Text4: Ticket; + fresh Text5,Text6,Text7: Ticket; + + recv_3(A,T, Rpa,Rb,A,B,Text4); + send_4(T,A, Text7,A,pk(A),B,pk(B),{Rpa,Rb,A,pk(A),B,pk(B),Text5}sk(T)); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6.template b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6.template new file mode 100644 index 0000000..e8b6a80 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-6.template @@ -0,0 +1,68 @@ +/* + * Modeled from ISO standard + * + * signature + * ttp + * five-pass + * mutual + * + * A initiates and also communicates with T + * + * parameters: + * + * NAME + * IA + * IB + * ResA + * ResB + * TokenAB + * TokenBA (although identical in both cases) + * TokenTA + * + */ +protocol NAME(A,B,T) +{ + role A + { + fresh Ra,Rpa: Nonce; + fresh Text1,Text4,Text8,Text9: Ticket; + var Rb: Nonce; + var Text2,Text3; + var Text5,Text6,Text7: Ticket; + + send_1(A,B, Ra,IA,Text1); + recv_2(B,A, IB,TokenBA); + send_3(A,T, Rpa,Rb,IA,IB,Text4); + recv_4(T,A, Text7,TokenTA); + claim(A,Running,B,Ra,Rb,Text8); + send_5(A,B, TokenAB); + + claim(A,Commit,B,Ra,Rb,Text2); + claim(A,Alive); + } + role B + { + var Ra,Rpa: Nonce; + var Text1,Text5,Text8,Text9: Ticket; + fresh Text2,Text3,Text4: Ticket; + fresh Rb: Nonce; + + recv_1(A,B, Ra,IA,Text1); + claim(B,Running,A,Ra,Rb,Text2); + send_2(B,A, IB,TokenBA); + recv_5(A,B, TokenAB); + + claim(B,Commit,A,Ra,Rb,Text8); + claim(B,Alive); + } + role T + { + var Rpa, Rb: Nonce; + var Text4: Ticket; + fresh Text5,Text6,Text7: Ticket; + + recv_3(A,T, Rpa,Rb,IA,IB,Text4); + send_4(T,A, Text7,TokenTA); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-1.cpp b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-1.cpp new file mode 100644 index 0000000..fd97211 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-1.cpp @@ -0,0 +1,12 @@ +#define NAME isoiec-9798-3-7-1 +#define IA A +#define IB B +#define ResA A,pk(A) +#define ResB B,pk(B) +#define TokenAB Text7,Ra,ResA,{Rb,ResA,Text3}sk(T),{Rb,Ra,B,A,Text6}sk(A) +#define TokenBA Ra,Rb,Text9,{A,Ra,Rb,B,Text8}sk(B) +#define TokenTA ResA,ResB,{Rpa,ResB,Text4}sk(T),{Rb,ResA,Text3}sk(T) + +#include "isoiec-9798-3-7.template" + + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-1.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-1.spdl new file mode 100644 index 0000000..516ceb0 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-1.spdl @@ -0,0 +1,66 @@ +/* + * Modeled from ISO standard + * + * signature + * ttp + * five-pass + * mutual + * + * B initiates and A communicates with T + * + * parameters: + * + * NAME + * IA + * IB + * ResA + * ResB + * TokenAB + * TokenBA (although identical in both cases) + * TokenTA + * + */ +protocol isoiec-9798-3-7-1(A,B,T) +{ + role A + { + fresh Ra,Rpa: Nonce; + var Rb: Nonce; + var Text1,Text3,Text4,Text5,Text8,Text9: Ticket; + fresh Text2,Text6,Text7: Ticket; + + recv_1(B,A, Rb,B,Text1 ); + send_2(A,T, Rpa,Rb,A,Text2 ); + recv_3(T,A, Text5, A,pk(A),B,pk(B),{Rpa,B,pk(B),Text4}sk(T),{Rb,A,pk(A),Text3}sk(T) ); + claim(A,Running,B,Ra,Rb,Text6); + send_4(A,B, A, Text7,Ra,A,pk(A),{Rb,A,pk(A),Text3}sk(T),{Rb,Ra,B,A,Text6}sk(A) ); + recv_5(B,A, Ra,Rb,Text9,{A,Ra,Rb,B,Text8}sk(B) ); + + claim(A,Commit,B,Ra,Rb,Text8); + claim(A,Alive); + } + role B + { + fresh Text1,Text8,Text9: Ticket; + fresh Rb: Nonce; + var Text3,Text4,Text6,Text7: Ticket; + var Ra,Rpa: Nonce; + + send_1(B,A, Rb,B,Text1 ); + recv_4(A,B, A, Text7,Ra,A,pk(A),{Rb,A,pk(A),Text3}sk(T),{Rb,Ra,B,A,Text6}sk(A) ); + claim(B,Running,A,Ra,Rb,Text8); + send_5(B,A, Ra,Rb,Text9,{A,Ra,Rb,B,Text8}sk(B) ); + + claim(B,Commit,A,Ra,Rb,Text6); + claim(B,Alive); + } + role T + { + var Rpa,Rb: Nonce; + var Text2: Ticket; + fresh Text3,Text4,Text5: Ticket; + + recv_2(A,T, Rpa,Rb,A,Text2 ); + send_3(T,A, Text5, A,pk(A),B,pk(B),{Rpa,B,pk(B),Text4}sk(T),{Rb,A,pk(A),Text3}sk(T) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-2.cpp b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-2.cpp new file mode 100644 index 0000000..6ca070b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-2.cpp @@ -0,0 +1,12 @@ +#define NAME isoiec-9798-3-7-2 +#define IA A +#define IB B +#define ResA A,pk(A) +#define ResB B,pk(B) +#define TokenAB Rpa,Text7,TokenTA,{Rb,Ra,B,A,Text6}sk(A) +#define TokenBA Ra,Rb,Text9,{Ra,Rb,A,B,Text8}sk(B) +#define TokenTA ResA,ResB,{Rpa,Rb,ResA,ResB,Text3}sk(T) + +#include "isoiec-9798-3-7.template" + + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-2.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-2.spdl new file mode 100644 index 0000000..98ce424 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7-2.spdl @@ -0,0 +1,68 @@ + + +/* + * Modeled from ISO standard + * + * signature + * ttp + * five-pass + * mutual + * + * B initiates and A communicates with T + * + * parameters: + * + * NAME + * IA + * IB + * ResA + * ResB + * TokenAB + * TokenBA (although identical in both cases) + * TokenTA + * + */ +protocol isoiec-9798-3-7-2(A,B,T) +{ + role A + { + fresh Ra,Rpa: Nonce; + var Rb: Nonce; + var Text1,Text3,Text4,Text5,Text8,Text9: Ticket; + fresh Text2,Text6,Text7: Ticket; + + recv_1(B,A, Rb,B,Text1 ); + send_2(A,T, Rpa,Rb,A,Text2 ); + recv_3(T,A, Text5, A,pk(A),B,pk(B),{Rpa,Rb,A,pk(A),B,pk(B),Text3}sk(T) ); + claim(A,Running,B,Ra,Rb,Text6); + send_4(A,B, A, Rpa,Text7,A,pk(A),B,pk(B),{Rpa,Rb,A,pk(A),B,pk(B),Text3}sk(T),{Rb,Ra,B,A,Text6}sk(A) ); + recv_5(B,A, Ra,Rb,Text9,{Ra,Rb,A,B,Text8}sk(B) ); + + claim(A,Commit,B,Ra,Rb,Text8); + claim(A,Alive); + } + role B + { + fresh Text1,Text8,Text9: Ticket; + fresh Rb: Nonce; + var Text3,Text4,Text6,Text7: Ticket; + var Ra,Rpa: Nonce; + + send_1(B,A, Rb,B,Text1 ); + recv_4(A,B, A, Rpa,Text7,A,pk(A),B,pk(B),{Rpa,Rb,A,pk(A),B,pk(B),Text3}sk(T),{Rb,Ra,B,A,Text6}sk(A) ); + claim(B,Running,A,Ra,Rb,Text8); + send_5(B,A, Ra,Rb,Text9,{Ra,Rb,A,B,Text8}sk(B) ); + + claim(B,Commit,A,Ra,Rb,Text6); + claim(B,Alive); + } + role T + { + var Rpa,Rb: Nonce; + var Text2: Ticket; + fresh Text3,Text4,Text5: Ticket; + + recv_2(A,T, Rpa,Rb,A,Text2 ); + send_3(T,A, Text5, A,pk(A),B,pk(B),{Rpa,Rb,A,pk(A),B,pk(B),Text3}sk(T) ); + } +} diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7.template b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7.template new file mode 100644 index 0000000..8d9491a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-3-7.template @@ -0,0 +1,67 @@ +/* + * Modeled from ISO standard + * + * signature + * ttp + * five-pass + * mutual + * + * B initiates and A communicates with T + * + * parameters: + * + * NAME + * IA + * IB + * ResA + * ResB + * TokenAB + * TokenBA (although identical in both cases) + * TokenTA + * + */ +protocol NAME(A,B,T) +{ + role A + { + fresh Ra,Rpa: Nonce; + var Rb: Nonce; + var Text1,Text3,Text4,Text5,Text8,Text9: Ticket; + fresh Text2,Text6,Text7: Ticket; + + recv_1(B,A, Rb,IB,Text1 ); + send_2(A,T, Rpa,Rb,IA,Text2 ); + recv_3(T,A, Text5, TokenTA ); + claim(A,Running,B,Ra,Rb,Text6); + send_4(A,B, IA, TokenAB ); + recv_5(B,A, TokenBA ); + + claim(A,Commit,B,Ra,Rb,Text8); + claim(A,Alive); + } + role B + { + fresh Text1,Text8,Text9: Ticket; + fresh Rb: Nonce; + var Text3,Text4,Text6,Text7: Ticket; + var Ra,Rpa: Nonce; + + send_1(B,A, Rb,IB,Text1 ); + recv_4(A,B, IA, TokenAB ); + claim(B,Running,A,Ra,Rb,Text8); + send_5(B,A, TokenBA ); + + claim(B,Commit,A,Ra,Rb,Text6); + claim(B,Alive); + } + role T + { + var Rpa,Rb: Nonce; + var Text2: Ticket; + fresh Text3,Text4,Text5: Ticket; + + recv_2(A,T, Rpa,Rb,IA,Text2 ); + send_3(T,A, Text5, TokenTA ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-1-udkey.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-1-udkey.spdl new file mode 100644 index 0000000..6a955d0 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-1-udkey.spdl @@ -0,0 +1,39 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * ccf + * one-pass + * unilateral + * + * Unidirectional key version. + * + * Modeling notes: + * + * - The keyed CCF (f_kab(x)) is modeled as f(x,kab) + */ +hashfunction f; + +protocol isoiec-9798-4-1-udkey(A,B) +{ + role A + { + fresh Text1,Text2: Ticket; + fresh TNA: Nonce; + + claim(A,Running,B,TNA,Text1); + send_1(A,B, TNA, Text2, f( TNA, Text1 ,k(A,B) ) ); + } + role B + { + var TNA: Nonce; + var Text1,Text2: Ticket; + + recv_1(A,B, TNA, Text2, f( TNA, Text1 ,k(A,B) ) ); + + claim(B,Commit,A,TNA,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-1.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-1.spdl new file mode 100644 index 0000000..f3a5b95 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-1.spdl @@ -0,0 +1,58 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010, Feb. 2011. + * + * History: + * + * - v2.0, Feb. 2011: + * Added key symmetry emulation protocol. + * + * ccf + * one-pass + * unilateral + * + * The identifier B is optional and may be omitted if the key is unidirectional. + * + * Modeling notes: + * + * - The keyed CCF (f_kab(x)) is modeled as f(x,kab) + */ +hashfunction f; + +protocol @keysymm-41(A,B) +{ + role A + { + var X,Y,Z: Ticket; + + recv_!1(B,A, f(X,Y,Z, k(A,B) ) ); + send_!2(A,B, f(X,Y,Z, k(B,A) ) ); + } + role B + { + } +} + +protocol isoiec-9798-4-1(A,B) +{ + role A + { + fresh Text1,Text2: Ticket; + fresh TNA: Nonce; + + claim(A,Running,B,TNA,Text1); + send_1(A,B, TNA, Text2, f( TNA, B, Text1 ,k(A,B) ) ); + } + role B + { + var TNA: Nonce; + var Text1,Text2: Ticket; + + recv_1(A,B, TNA, Text2, f( TNA, B, Text1 ,k(A,B) ) ); + + claim(B,Commit,A,TNA,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-2-udkey.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-2-udkey.spdl new file mode 100644 index 0000000..c1e292f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-2-udkey.spdl @@ -0,0 +1,43 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * ccf + * unilateral + * two-pass + * + * Unidirectional key version. + * + * Modeling notes: + * + * - The keyed CCF (f_kab(x)) is modeled as f(x,kab) + */ +hashfunction f; + +protocol isoiec-9798-4-2-udkey(A,B) +{ + role A + { + var Rb: Nonce; + var Text1: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, Rb,Text1 ); + claim(A,Running,B,Rb,Text2); + send_2(A,B, Text3, f( Rb, Text2, k(A,B)) ); + } + role B + { + fresh Rb: Nonce; + fresh Text1: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, Rb,Text1 ); + recv_2(A,B, Text3, f( Rb, Text2, k(A,B)) ); + + claim(B,Commit,A,Rb,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-2.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-2.spdl new file mode 100644 index 0000000..d2bd4a9 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-2.spdl @@ -0,0 +1,62 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010, Feb. 2011. + * + * History: + * + * - v2.0, Feb. 2011: + * Added key symmetry emulation protocol. + * + * ccf + * unilateral + * two-pass + * + * The identifier B is optional and may be omitted if the key is unidirectional. + * + * Modeling notes: + * + * - The keyed CCF (f_kab(x)) is modeled as f(x,kab) + */ +hashfunction f; + +protocol @keysymm-42(A,B) +{ + role A + { + var X,Y,Z: Ticket; + + recv_!1(B,A, f(X,Y,Z, k(A,B) ) ); + send_!2(A,B, f(X,Y,Z, k(B,A) ) ); + } + role B + { + } +} + +protocol isoiec-9798-4-2(A,B) +{ + role A + { + var Rb: Nonce; + var Text1: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, Rb,Text1 ); + claim(A,Running,B,Rb,Text2); + send_2(A,B, Text3, f( Rb, B, Text2, k(A,B)) ); + } + role B + { + fresh Rb: Nonce; + fresh Text1: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, Rb,Text1 ); + recv_2(A,B, Text3, f( Rb, B, Text2, k(A,B)) ); + + claim(B,Commit,A,Rb,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-3-udkey.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-3-udkey.spdl new file mode 100644 index 0000000..4371591 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-3-udkey.spdl @@ -0,0 +1,50 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * ccf + * two-pass + * mutual + * + * Unidirectional key version. + * + * Modeling notes: + * + * - The keyed CCF (f_kab(x)) is modeled as f(x,kab) + */ +hashfunction f; + +protocol isoiec-9798-4-3-udkey(A,B) +{ + role A + { + fresh Text1,Text2: Ticket; + var Text3,Text4: Ticket; + fresh TNa: Nonce; + var TNb: Nonce; + + claim(A,Running,B,TNa,Text1); + send_1(A,B, TNa, Text2, f(TNa,Text1, k(A,B) ) ); + recv_2(B,A, TNb, Text4, f(TNb,Text3, k(B,A) ) ); + + claim(A,Commit,B,TNb,Text3); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var TNa: Nonce; + fresh TNb: Nonce; + var Text1,Text2: Ticket; + fresh Text3,Text4: Ticket; + + recv_1(A,B, TNa, Text2, f(TNa,Text1, k(A,B) ) ); + claim(B,Running,A,TNb,Text3); + send_2(B,A, TNb, Text4, f(TNb,Text3, k(B,A) ) ); + + claim(B,Commit,A,TNa,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-3.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-3.spdl new file mode 100644 index 0000000..a5902e2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-3.spdl @@ -0,0 +1,69 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010, Feb. 2011. + * + * History: + * + * - v2.0, Feb. 2011: + * Added key symmetry emulation protocol. + * + * ccf + * two-pass + * mutual + * + * The identifiers B,A are optional and may be (independently) be omitted if the key is unidirectional. + * + * Modeling notes: + * + * - The keyed CCF (f_kab(x)) is modeled as f(x,kab) + */ +hashfunction f; + +protocol @keysymm-43(A,B) +{ + role A + { + var X,Y,Z: Ticket; + + recv_!1(B,A, f(X,Y,Z, k(A,B) ) ); + send_!2(A,B, f(X,Y,Z, k(B,A) ) ); + } + role B + { + } +} + +protocol isoiec-9798-4-3(A,B) +{ + role A + { + fresh Text1,Text2: Ticket; + var Text3,Text4: Ticket; + fresh TNa: Nonce; + var TNb: Nonce; + + claim(A,Running,B,TNa,Text1); + send_1(A,B, TNa, Text2, f(TNa,B,Text1, k(A,B) ) ); + recv_2(B,A, TNb, Text4, f(TNb,A,Text3, k(A,B) ) ); + + claim(A,Commit,B,TNb,Text3); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var TNa: Nonce; + fresh TNb: Nonce; + var Text1,Text2: Ticket; + fresh Text3,Text4: Ticket; + + recv_1(A,B, TNa, Text2, f(TNa,B,Text1, k(A,B) ) ); + claim(B,Running,A,TNb,Text3); + send_2(B,A, TNb, Text4, f(TNb,A,Text3, k(A,B) ) ); + + claim(B,Commit,A,TNa,Text1); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-4-udkey.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-4-udkey.spdl new file mode 100644 index 0000000..27e5466 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-4-udkey.spdl @@ -0,0 +1,52 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010 + * + * ccf + * mutual + * three-pass + * + * Unidirectional key version. + * + * Modeling notes: + * + * - The keyed CCF (f_kab(x)) is modeled as f(x,kab) + */ +hashfunction f; + +protocol isoiec-9798-4-4-udkey(A,B) +{ + role A + { + fresh Ra: Nonce; + var Rb: Nonce; + var Text1,Text4,Text5: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, Rb, Text1 ); + claim(A,Running,B,Ra,Rb,Text2); + send_2(A,B, Ra, Text3, f(Ra,Rb,Text2, k(A,B) ) ); + recv_3(B,A, Text5, f(Rb,Ra,Text4, k(B,A) ) ); + + claim(A,Commit,B,Ra,Rb,Text2,Text4); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var Ra: Nonce; + fresh Rb: Nonce; + fresh Text1,Text4,Text5: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, Rb, Text1 ); + recv_2(A,B, Ra, Text3, f(Ra,Rb,Text2, k(A,B) ) ); + claim(B,Running,A,Ra,Rb,Text2,Text4); + send_3(B,A, Text5, f(Rb,Ra,Text4, k(B,A) ) ); + + claim(B,Commit,A,Ra,Rb,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-4.spdl b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-4.spdl new file mode 100644 index 0000000..f796369 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ISO-9798/isoiec-9798-4-4.spdl @@ -0,0 +1,75 @@ +/* + * Modeled from ISO/IEC 9798 + * Modeler: Cas Cremers, Dec. 2010, Feb. 2011. + * + * History: + * + * - v2.0, Feb. 2011: + * Added key symmetry emulation protocol. + * + * ccf + * mutual + * three-pass + * + * The identifier B is optional and may be omitted if the key is unidirectional. + * + * Modeling notes: + * + * - The keyed CCF (f_kab(x)) is modeled as f(x,kab) + */ +hashfunction f; + +protocol @keysymm-44(A,B) +{ + role A + { + var X,Y,Z: Ticket; + + recv_!1(B,A, f(X,Y,Z, k(A,B) ) ); + send_!2(A,B, f(X,Y,Z, k(B,A) ) ); + } + role B + { + var X,Y,Z,ZZ: Ticket; + + recv_!3(A,B, f(X,Y,Z,ZZ, k(A,B) ) ); + send_!4(B,A, f(X,Y,Z,ZZ, k(B,A) ) ); + } +} + +protocol isoiec-9798-4-4(A,B) +{ + role A + { + fresh Ra: Nonce; + var Rb: Nonce; + var Text1,Text4,Text5: Ticket; + fresh Text2,Text3: Ticket; + + recv_1(B,A, Rb, Text1 ); + claim(A,Running,B,Ra,Rb,Text2); + send_2(A,B, Ra, Text3, f(Ra,Rb,B,Text2, k(A,B) ) ); + recv_3(B,A, Text5, f(Rb,Ra,Text4, k(A,B) ) ); + + claim(A,Commit,B,Ra,Rb,Text2,Text4); + claim(A,Alive); + claim(A,Weakagree); + } + role B + { + var Ra: Nonce; + fresh Rb: Nonce; + fresh Text1,Text4,Text5: Ticket; + var Text2,Text3: Ticket; + + send_1(B,A, Rb, Text1 ); + recv_2(A,B, Ra, Text3, f(Ra,Rb,B,Text2, k(A,B) ) ); + claim(B,Running,A,Ra,Rb,Text2,Text4); + send_3(B,A, Text5, f(Rb,Ra,Text4, k(A,B) ) ); + + claim(B,Commit,A,Ra,Rb,Text2); + claim(B,Alive); + claim(B,Weakagree); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/BKE.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/BKE.spdl new file mode 100644 index 0000000..8342bd6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/BKE.spdl @@ -0,0 +1,40 @@ +/* + Bilateral Key Exchange with Public Key protocol (BKEPK) +*/ + +usertype SessionKey; + +hashfunction hash; + +protocol bke(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir: SessionKey; + + send_1 (I,R, { ni,I }pk(R) ); + recv_2 (R,I, { hash(ni),nr,R,kir }pk(I) ); + send_3 (I,R, { hash(nr) }kir ); + claim_4 (I, Secret, kir ); + //claim_5 (I, Niagree ); + //claim_6 (I, Nisynch ); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + fresh kir: SessionKey; + + recv_1 (I,R, { ni,I }pk(R) ); + send_2 (R,I, { hash(ni),nr,R,kir }pk(I) ); + recv_3 (I,R, { hash(nr) }kir ); + claim_7 (R, Secret, kir ); + //claim_8 (R, Niagree ); + //claim_9 (R, Nisynch ); + } +} + + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-ban-concrete.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-ban-concrete.spdl new file mode 100644 index 0000000..48f52d8 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-ban-concrete.spdl @@ -0,0 +1,67 @@ +# BAN concrete Andrew Secure RPC +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/andrewBAN2.html +# +# Note: +# The shared key between I and R is modelled as k(I,R) currently +# there is no way to express that this key is equal to k(R,I) +# In order to overcome this a 'dummy' role X has been hadded that recrypts +# a given term crypted with k(I,R) with k(R,I) +# +# Note: +# Recv 4 by the Initatior has been placed after the synchronisation claim +# as it allows trivial synchronisation attacks otherwise (the message is +# completely fresh and can therefore always be replaced by an arbitrary value +# created by the intruder) which are not considered in SPORE +# + +usertype SessionKey; +const Fresh: Function; + +protocol @swapkey(X) +{ + # Protocol added to work around the symmetry problems where k(I,R) != k(R,I) + role X + { + var I,R: Agent; + var T:Ticket; + recv_!X1(X,X,I,R,{T}k(I,R)); + send_!X2(X,X,{T}k(R,I)); + } +} + +protocol andrew-Concrete(I,R) +{ + + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir: SessionKey; + + send_1(I,R, I,ni ); + recv_2(R,I, {ni,kir}k(I,R) ); + send_3(I,R, {ni}kir); + claim_I1(I,Secret,kir); + claim_I2(I,Nisynch); + claim_I3(I,Empty,(Fresh,kir)); + recv_6(R,I, nr); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + fresh kir: SessionKey; + + recv_1(I,R, I,ni ); + send_2(R,I, {ni,kir}k(I,R) ); + recv_3(I,R, {ni}kir); + send_6(R,I, nr); + claim_R1(R,Secret,kir); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,kir)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-ban.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-ban.spdl new file mode 100644 index 0000000..5118604 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-ban.spdl @@ -0,0 +1,52 @@ +# BAN modified Andrew Secure RPC +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/andrewBAN.html +# +# Note: +# The shared key between I and R is modelled as k(I,R) currently +# there is no way to express that this key is equal to k(R,I) +# So it is possile that certain attacks that use this property are not found +# +# Note: +# According to SPORE there are no known attacks on this protocol +# +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol andrew-Ban(I,R) +{ + role I + { + fresh ni: Nonce; + var nr,nr2: Nonce; + var kir: SessionKey; + + send_1(I,R, I,{ni}k(I,R) ); + recv_2(R,I, {ni,nr}k(I,R) ); + send_3(I,R, {nr}k(I,R) ); + recv_4(R,I, {kir,nr2,ni}k(I,R) ); + claim_I1(I,Nisynch); + claim_I2(I,Niagree); + claim_I3(I,Secret, kir); + claim_I5(I,Empty, (Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr,nr2: Nonce; + fresh kir: SessionKey; + + recv_1(I,R, I,{ni}k(I,R) ); + send_2(R,I, {ni,nr}k(I,R) ); + recv_3(I,R, {nr}k(I,R) ); + send_4(R,I, {kir,nr2,ni}k(I,R) ); + claim_R1(R,Nisynch); + claim_R2(R,Niagree); + claim_R3(R,Secret, kir); + claim_R5(R,Empty, (Fresh,kir)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-lowe-ban.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-lowe-ban.spdl new file mode 100644 index 0000000..04e15f2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/andrew-lowe-ban.spdl @@ -0,0 +1,57 @@ +# Lowe modified BAN concrete Andrew Secure RPC +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/andrewLowe.html +# +# Note: +# The shared key between I and R is modelled as k(I,R) currently +# there is no way to express that this key is equal to k(R,I) +# So it is possile that certain attacks that use this property are not found +# +# Note: +# Recv 4 by the Initatior has been placed after the synchronisation claim +# as it allows trivial synchronisation attacks otherwise (the message is +# completely fresh and can therefore always be replaced by an arbitrary value +# created by the intruder) which are not considered in SPORE +# +# Note: +# According to SPORE there are no known attacks on this protocol +# + +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol andrew-LoweBan(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir: SessionKey; + + send_1(I,R, I,ni ); + recv_2(R,I, {ni,kir,R}k(I,R) ); + send_3(I,R, {ni}kir ); + claim_I1(I,Nisynch); + claim_I2(I,Secret, kir); + claim_I3(I,Empty, (Fresh,kir)); + recv_4(R,I, nr ); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + fresh kir: SessionKey; + + recv_1(I,R, I,ni ); + send_2(R,I, {ni,kir,R}k(I,R) ); + recv_3(I,R, {ni}kir ); + send_4(R,I, nr ); + claim_R1(R,Nisynch); + claim_R2(R,Secret, kir); + claim_R3(R,Empty, (Fresh,kir)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/boyd.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/boyd.spdl new file mode 100644 index 0000000..0a9c755 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/boyd.spdl @@ -0,0 +1,56 @@ +usertype Sessionkey; +usertype Macseed; +const m: Function; +secret unm: Function; +const f: Function; + +inversekeys (m, unm); + +/* + * Boyd key agreement + * + * Boyd & Mathuria: Protocols for authentication and key establishment + * (2003) p. 101 + * + * Note that MAC_ks(x) has been interpreted as MAC(x,ks); this + * assumption causes some possible false attacks. + */ + +protocol boyd(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var ks: Macseed; + + send_1 (I,S, I,R, ni ); + recv_3 (R,I, { I,R, ks }k(I,S), m(ni, m(ks,ni,nr)), nr ); + send_4 (I,R, m(nr, m(ks,ni,nr)) ); + + claim_6 (I, Secret, m(ks,ni,nr) ); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + var ks: Macseed; + + recv_2 (S,R, { I,R, ks }k(I,S), { I,R, ks }k(R,S), ni ); + send_3 (R,I, { I,R, ks }k(I,S), m(ni, m(ks,ni,nr)), nr ); + recv_4 (I,R, m(nr, m(ks,ni,nr)) ); + + claim_10 (R, Secret, m(ks,ni,nr)); + } + + role S + { + var ni,nr: Nonce; + fresh ks: Macseed; + + recv_1 (I,S, I,R, ni ); + send_2 (S,R, { I,R, ks }k(I,S), { I,R, ks }k(R,S), ni ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ccitt509-ban3.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ccitt509-ban3.spdl new file mode 100644 index 0000000..bdf146d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ccitt509-ban3.spdl @@ -0,0 +1,39 @@ +# BAN modified version of CCITT X.509 (3) +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/ccittx509_3BAN.html +# +# Note: +# The protocol description also states that Xa and Ya should be fresh +# this can not be verified using scyther +# +# Note: +# According to SPORE there are no known attacks on this protocol +# + +protocol ccitt509-ban3(I,R) +{ + role I + { + fresh Na,Xa,Ya: Nonce; + var Xb,Nb,Yb: Nonce; + + send_1(I,R, I,{Na, R, Xa,{Ya}pk(R)}sk(I)); + recv_2(R,I, R,{Nb, I, Na, Xb,{Yb}pk(I)}sk(R)); + send_3(I,R, I,{R, Nb}sk(I)); + claim_4(I,Nisynch); + } + + role R + { + var Na,Xa,Ya: Nonce; + fresh Xb,Yb,Nb: Nonce; + + recv_1(I,R, I,{Na, R, Xa,{Ya}pk(R)}sk(I)); + send_2(R,I, R,{Nb, I, Na, Xb,{Yb}pk(I)}sk(R)); + recv_3(I,R, I,{R, Nb}sk(I)); + claim_5(R,Nisynch); + # There should also be Fresh Xa and Fresh Ya claims here + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/denning-sacco-lowe.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/denning-sacco-lowe.spdl new file mode 100644 index 0000000..d5c3182 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/denning-sacco-lowe.spdl @@ -0,0 +1,66 @@ +# Lowe modified Denning-Sacco shared key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/denningSaccoLowe.html +# +# Note: +# According to SPORE there are no attacks on this protocol, scyther +# finds one however. This has to be investigated further. + +usertype Key; +usertype SessionKey; +usertype TimeStamp; +usertype ExpiredTimeStamp; +usertype PseudoFunction; +const dec: PseudoFunction; +const Fresh: Function; +const Compromised: Function; + +protocol denningSacco-Lowe(I,R,S) +{ + role I + { + var W: Ticket; + var Kir: SessionKey; + var T: TimeStamp; + var Nr: Nonce; + + send_1(I,S, I,R ); + recv_2(S,I, {R, Kir, T, W}k(I,S) ); + send_3(I,R, W); + recv_4(R,I, {Nr}Kir); + send_5(I,R, {{Nr}dec}Kir); + claim_I1(I,Niagree); + claim_I2(I,Nisynch); + claim_I3(I,Secret,Kir); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + var Kir: SessionKey; + var T: TimeStamp; + fresh Nr: Nonce; + + recv_3(I,R, {Kir,I,T}k(R,S)); + send_4(R,I, {Nr}Kir); + recv_5(I,R, {{Nr}dec}Kir); + claim_R1(R,Niagree); + claim_R2(R,Nisynch); + claim_R3(R,Secret,Kir); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var W: Ticket; + fresh Kir: SessionKey; + fresh T: TimeStamp; + + recv_1(I,S, I,R ); + send_2(S,I, {R, Kir, T, {Kir, I,T}k(R,S)}k(I,S)); + claim_x(S, Secret, Kir); + } +} + + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/denning-sacco.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/denning-sacco.spdl new file mode 100644 index 0000000..00167e9 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/denning-sacco.spdl @@ -0,0 +1,55 @@ +# Denning-Sacco shared key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/denningSacco.html +# + +usertype Key; +usertype SessionKey; +usertype TimeStamp; +usertype ExpiredTimeStamp; +const Fresh: Function; +const Compromised: Function; + +protocol denningSacco(I,R,S) +{ + role I + { + var W: Ticket; + var Kir: SessionKey; + var T: TimeStamp; + + send_1(I,S, I,R ); + recv_2(S,I, {R, Kir, T, W}k(I,S) ); + send_3(I,R, W); + claim_I1(I,Niagree); + claim_I2(I,Nisynch); + claim_I3(I,Secret,Kir); + claim_I4(I,Empty, (Fresh,Kir)); + } + + role R + { + var Kir: SessionKey; + var T: TimeStamp; + + recv_3(I,R, {Kir,I,T}k(R,S)); + claim_R1(R,Niagree); + claim_R2(R,Nisynch); + claim_R3(R,Secret,Kir); + claim_R4(R,Empty, (Fresh,Kir)); + } + + role S + { + var W: Ticket; + fresh Kir: SessionKey; + fresh T: TimeStamp; + + recv_1(I,S, I,R ); + send_2(S,I, {R, Kir, T, {Kir, I,T}k(R,S)}k(I,S)); + } +} + + + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/gong-nonce-b.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/gong-nonce-b.spdl new file mode 100644 index 0000000..09bde6d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/gong-nonce-b.spdl @@ -0,0 +1,60 @@ +usertype Sessionkey; +usertype Keypart; +hashfunction f; + +/* + * Gong nonce based alternative + * + * Boyd & Mathuria: Protocols for authentication and key establishment + * (2003) p. 101 + */ + +protocol gongnonceb(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + fresh ki: Keypart; + var kr: Keypart; + + send_1 (I,S, I,R, { I,S,I, ki, R }k(I,S), ni ); + recv_4 (S,I, { S,I,R,kr,I }k(I,S), { R,I,ni }f(ki,kr), nr ); + send_5 (I,R, { I,R,nr }f(ki,kr) ); + + claim_6 (I, Secret, ki); + claim_7 (I, Secret, kr); + claim_8 (I, Nisynch); + claim_9 (I, Niagree); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + fresh kr: Keypart; + var ki: Keypart; + + recv_2 (S,R, I,R, { S,R,I, ki, R }k(R,S), ni ); + send_3 (R,S, { R,S,R,kr,I }k(R,S), { R,I, ni }f(ki,kr), nr ); + recv_5 (I,R, { I,R,nr }f(ki,kr) ); + + claim_10 (R, Secret, ki); + claim_11 (R, Secret, kr); + claim_12 (R, Nisynch); + claim_13 (R, Niagree); + } + + role S + { + var ni,nr: Nonce; + var ki,kr: Keypart; + var T; + + recv_1 (I,S, I,R, { I,S,I, ki, R }k(I,S), ni ); + send_2 (S,R, I,R, { S,R,I, ki, R }k(R,S), ni ); + recv_3 (R,S, { R,S,R,kr,I }k(R,S), T, nr ); + send_4 (S,I, { S,I,R,kr,I }k(I,S), T, nr ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/gong-nonce.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/gong-nonce.spdl new file mode 100644 index 0000000..594e1b9 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/gong-nonce.spdl @@ -0,0 +1,57 @@ +/* + * From Boyd Mathuria + * + * To check: 3.38 or other? + * + */ +usertype Sessionkey; +usertype Keypart; + +protocol gongnonce(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + fresh ki: Keypart; + var kr: Keypart; + + send_1 (I,R, I,R,ni ); + recv_3 (S,I, { S,I,R, kr, I, ni }k(I,S), nr); + send_4 (I,S, { I,S,I, ki, R, nr }k(I,S) ); + + claim_6 (I, Secret, ki); + claim_7 (I, Secret, kr); + claim_8 (I, Nisynch); + claim_9 (I, Niagree); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + fresh kr: Keypart; + var ki: Keypart; + + recv_1 (I,R, I,R,ni ); + send_2 (R,S, I,R, nr, { R,S,R, kr, I,ni }k(R,S)); + recv_5 (S,R, { S,R,I, ki, R, nr }k(R,S) ); + + claim_10 (R, Secret, ki); + claim_11 (R, Secret, kr); + claim_12 (R, Nisynch); + claim_13 (R, Niagree); + } + + role S + { + var ni,nr: Nonce; + var ki,kr: Keypart; + + recv_2 (R,S, I,R, nr, { R,S,R, kr, I,ni }k(R,S)); + send_3 (S,I, { S,I,R, kr, I, ni }k(I,S), nr); + recv_4 (I,S, { I,S,I, ki, R, nr }k(I,S) ); + send_5 (S,R, { S,R,I, ki, R, nr }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/isoiec11770-2-13.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/isoiec11770-2-13.spdl new file mode 100644 index 0000000..5db1533 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/isoiec11770-2-13.spdl @@ -0,0 +1,42 @@ +usertype Sessionkey; +usertype Ticket; + +protocol isoiec11770213(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir: Sessionkey; + + send_1 (I,R, ni); + recv_4 (R,I, { ni,kir,R }k(I,S) ); + + claim_5 (I, Secret, kir); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + fresh kir: Sessionkey; + var T; + + recv_1 (I,R, ni); + send_2 (R,S, { nr,ni,I,kir }k(R,S) ); + recv_3 (S,R, { nr, I }k(R,S), T ); + send_4 (R,I, T ); + + claim_6 (R, Secret, kir); + } + + role S + { + var ni,nr: Nonce; + var kir: Sessionkey; + + recv_2 (R,S, { nr,ni,I,kir }k(R,S) ); + send_3 (S,R, { nr, I }k(R,S), { ni,kir,R }k(I,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow-v2.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow-v2.spdl new file mode 100644 index 0000000..638a54b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow-v2.spdl @@ -0,0 +1,55 @@ +# Kao Chow Authentication v.2 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/kaoChow2.html +# + +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol kaochow-2(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir,kt: SessionKey; + + send_1 (I,S, I,R,ni); + recv_3 (R,I, R, {I,R,ni,kir,kt}k(I,S), {ni, kir}kt, nr ); + send_4 (I,R, {nr,kir}kt ); + + claim_I1 (I, Nisynch); + claim_I2 (I, Niagree); + claim_I3 (I, Secret, kir); + claim_I4 (I, Empty, (Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + var kir,kt: SessionKey; + var T: Ticket; + + recv_2 (S,R, T, { I,R,ni,kir,kt }k(R,S) ); + send_3 (R,I, R, T, {ni, kir}kt, nr ); + recv_4 (I,R, {nr,kir}kt ); + + claim_R1 (R, Nisynch); + claim_R2 (R, Niagree); + claim_R3 (R, Secret, kir); + claim_R4 (R, Empty, (Fresh,kir)); + } + + role S + { + var ni: Nonce; + fresh kir, kt: SessionKey; + + recv_1 (I,S, I,R,ni); + send_2 (S,R, {I,R,ni,kir,kt}k(I,S), { I,R,ni,kir,kt }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow-v3.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow-v3.spdl new file mode 100644 index 0000000..88cef24 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow-v3.spdl @@ -0,0 +1,59 @@ +# Kao Chow Authentication v.3 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/kaoChow3.html +# + +usertype SessionKey; +usertype ExpiredTimeStamp; +usertype TimeStamp; +const Fresh: Function; +const Compromised: Function; + +protocol kaochow-3(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir,kt: SessionKey; + var T2: Ticket; + + send_1 (I,S, I,R,ni); + recv_3 (R,I, {I,R,ni,kir,kt}k(I,S), {ni, kir}kt, nr, T2 ); + send_4 (I,R, {nr,kir}kt, T2 ); + + claim_I1 (I, Nisynch); + claim_I2 (I, Niagree); + claim_I3 (I, Secret, kir); + claim_I4 (I, Empty, (Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + var kir,kt: SessionKey; + var T: Ticket; + fresh tr: TimeStamp; + + recv_2 (S,R, T, { I,R,ni,kir,kt }k(R,S) ); + send_3 (R,I, T, {ni, kir}kt, nr, {I,R,tr,kir}k(R,S) ); + recv_4 (I,R, {nr,kir}kt, {I,R,tr,kir}k(R,S) ); + + claim_R1 (R, Nisynch); + claim_R2 (R, Niagree); + claim_R3 (R, Secret, kir); + claim_R4 (R, Empty, (Fresh,kir)); + } + + role S + { + var ni: Nonce; + fresh kir, kt: SessionKey; + + recv_1 (I,S, I,R,ni); + send_2 (S,R, {I,R,ni,kir,kt}k(I,S), { I,R,ni,kir,kt }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow.spdl new file mode 100644 index 0000000..1c6c827 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/kaochow.spdl @@ -0,0 +1,55 @@ +# Kao Chow Authentication v.1 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/kaoChow1.html +# + +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol kaochow(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir: SessionKey; + + send_1 (I,S, I,R,ni); + recv_3 (R,I, {I,R,ni,kir}k(I,S), {ni}kir, nr ); + send_4 (I,R, {nr}kir ); + + claim_I1 (I, Nisynch); + claim_I2 (I, Niagree); + claim_I3 (I, Secret, kir); + claim_I4 (I, Empty, (Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + var kir: SessionKey; + var T; + + recv_2 (S,R, T, { I,R,ni,kir }k(R,S) ); + send_3 (R,I, T, {ni}kir, nr ); + recv_4 (I,R, {nr}kir ); + + claim_R1 (R, Nisynch); + claim_R2 (R, Niagree); + claim_R3 (R, Secret, kir); + claim_R4 (R, Empty, (Fresh,kir)); + } + + role S + { + var ni: Nonce; + fresh kir: SessionKey; + + recv_1 (I,S, I,R,ni); + send_2 (S,R, {I,R,ni,kir}k(I,S), { I,R,ni,kir }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ksl.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ksl.spdl new file mode 100644 index 0000000..3595cf2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ksl.spdl @@ -0,0 +1,75 @@ +# KSL +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/ksl.html +# +# + + +usertype Server, SessionKey, TimeStamp, TicketKey; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + + + +protocol ksl(I,R,S) +{ + role I + { + fresh Ni, Mi: Nonce; + var Nc, Mr: Nonce; + var T: Ticket; + var Kir: SessionKey; + + send_1(I,R, Ni, I); + recv_4(R,I, { Ni,R,Kir }k(I,S), T, Nc, {Ni}Kir ); + send_5(I,R, { Nc }Kir ); + + send_6(I,R, Mi,T ); + recv_7(R,I, Mr,{Mi}Kir ); + send_8(I,R, {Mr}Kir ); + + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty, (Fresh, Kir)); + } + + role R + { + var Ni,Mi: Nonce; + fresh Nr,Nc,Mr: Nonce; + var Kir: SessionKey; + fresh Kbb: TicketKey; + fresh Tr: TimeStamp; + var T: Ticket; + + recv_1(I,R, Ni, I); + send_2(R,S, Ni, I, Nr, R ); + recv_3(S,R, { Nr, I, Kir }k(R,S), T ); + send_4(R,I, T, { Tr, I, Kir }Kbb, Nc, {Ni}Kir ); + recv_5(I,R, { Nc }Kir ); + + recv_6(I,R, Mi,{ Tr, I, Kir }Kbb ); + send_7(R,I, Mr,{Mi}Kir ); + recv_8(I,R, {Mr}Kir ); + + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni, Nr: Nonce; + fresh Kir: SessionKey; + + recv_2(R,S, Ni, I, Nr, R ); + send_3(S,R, { Nr, I, Kir }k(R,S), { Ni,R,Kir }k(I,S) ); + } +} + + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/needham-schroeder-sk-amend.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/needham-schroeder-sk-amend.spdl new file mode 100644 index 0000000..189093d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/needham-schroeder-sk-amend.spdl @@ -0,0 +1,66 @@ +# Amended Needham Schroeder Symmetric Key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/nssk_amended.html +# +# +# Note: +# According to SPORE there are no attacks on this protocol, scyther +# finds one however. This has to be investigated further. + + + +# Model dec that is invertible by inc +const dec,inc: Function; +inversekeys(dec,inc); +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol needhamschroedersk-amend(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var Kir: SessionKey; + var T,T2: Ticket; + + send_1(I,R,I); + recv_2(R,I,T); + send_3(I,S,(I,R,Ni,T)); + recv_4(S,I, {Ni,R,Kir,T2}k(I,S)); + send_5(I,R,T2); + recv_6(R,I,{Nr}Kir); + send_7(I,R,{{Nr}dec}Kir); + + claim_I2(I,Secret,Kir); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh Nr: Nonce; + var Kir: SessionKey; + + recv_1(I,R,I); + send_2(R,I,{I,Nr}k(R,S)); + recv_5(I,R,{Kir,Nr,I}k(R,S)); + send_6(R,I,{Nr}Kir); + recv_7(I,R,{{Nr}dec}Kir); + claim_R1(R,Secret,Nr); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni,Nr: Nonce; + fresh Kir: SessionKey; + recv_3(I,S,(I,R,Ni,{I,Nr}k(R,S))); + send_4(S,I,{Ni,R,Kir,{Kir,Nr,I}k(R,S)}k(I,S)); + } + +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/needham-schroeder-sk.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/needham-schroeder-sk.spdl new file mode 100644 index 0000000..71a7e6c --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/needham-schroeder-sk.spdl @@ -0,0 +1,56 @@ +# Needham Schroeder Symmetric Key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/nssk.html +# +# + + +# Model dec that is invertible by inc +const dec,inc: Function; +inversekeys(dec,inc); +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol needhamschroedersk(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var Kir: SessionKey; + var T: Ticket; + + send_1(I,S,(I,R,Ni)); + recv_2(S,I, {Ni,R,Kir,T}k(I,S)); + send_3(I,R,T); + recv_4(R,I,{Nr}Kir); + send_5(I,R,{{Nr}dec}Kir); + claim_I2(I,Secret,Kir); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh Nr: Nonce; + var Kir: SessionKey; + + recv_3(I,R,{Kir,I}k(R,S)); + send_4(R,I,{Nr}Kir); + recv_5(I,R,{{Nr}dec}Kir); + claim_R1(R,Secret,Kir); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni: Nonce; + fresh Kir: SessionKey; + recv_1(I,S,(I,R,Ni)); + send_2(S,I,{Ni,R,Kir,{Kir,I}k(R,S)}k(I,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/new.txt b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/new.txt new file mode 100644 index 0000000..dbba198 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/new.txt @@ -0,0 +1,5 @@ +denning-sacco-lowe.spdl +wmf.spdl +wmf-lowe.spdl +andrew-ban-concrete.spdl +yahalom-ban-paulson.spdl diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ns3.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ns3.spdl new file mode 100644 index 0000000..b83afa7 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/ns3.spdl @@ -0,0 +1,41 @@ +/* + * Needham-Schroeder protocol + */ + +// The protocol description + +protocol ns3(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {ni,I}pk(R) ); + recv_2(R,I, {ni,nr}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + //claim_i3(I,Alive); + claim_i4(I,Niagree); + claim_i5(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {ni,I}pk(R) ); + send_2(R,I, {ni,nr}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + //claim_r3(R,Alive); + claim_r4(R,Niagree); + claim_r5(R,Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/nsl3.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/nsl3.spdl new file mode 100644 index 0000000..a4bfef5 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/nsl3.spdl @@ -0,0 +1,39 @@ +/* + * Needham-Schroeder-Lowe protocol + */ + +// The protocol description + +protocol nsl3(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {ni,I}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {ni,I}pk(R) ); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/otwayrees.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/otwayrees.spdl new file mode 100644 index 0000000..bed12ad --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/otwayrees.spdl @@ -0,0 +1,56 @@ +# Otway Rees +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/otwayRees.html +# + + +const Fresh: Function; +const Compromised: Function; + +usertype String,SessionKey; + +protocol otwayrees(I,R,S) +{ + role I + { + fresh Ni : Nonce; + fresh M : String; + var Kir : SessionKey; + + send_1(I,R, M,I,R,{Ni,M,I,R}k(I,S) ); + recv_4(R,I, M,{Ni,Kir}k(I,S) ); + + claim_I1(I, Secret,Kir); + claim_I2(I, Nisynch); + claim_I3(I, Empty, (Fresh,Kir)); + } + + role R + { + var M : String; + fresh Nr : Nonce; + var Kir : SessionKey; + var T1,T2: Ticket; + + recv_1(I,R, M,I,R, T1 ); + send_2(R,S, M,I,R, T1, { Nr,M,I,R }k(R,S) ); + recv_3(S,R, M, T2, { Nr,Kir }k(R,S) ); + send_4(R,I, M, T2 ); + + claim_R1(R, Secret,Kir); + claim_R2(R, Nisynch); + claim_R3(R, Empty, (Fresh,Kir)); + } + + role S + { + var Ni,Nr : Nonce; + var M : String; + fresh Kir : SessionKey; + + recv_2(R,S, M,I,R, { Ni,M,I,R}k(I,S), { Nr,M,I,R }k(R,S) ); + send_3(S,R, M, { Ni,Kir }k(I,S) , { Nr,Kir }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/soph.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/soph.spdl new file mode 100644 index 0000000..3b10851 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/soph.spdl @@ -0,0 +1,21 @@ + +protocol soph(I,R) +{ + role I + { + fresh ni: Nonce; + + send_1(I,R, {I,ni}pk(R) ); + recv_2(R,I, ni ); + claim_3(I,Niagree); + } + + role R + { + var ni: Nonce; + + recv_1(I,R, {I,ni}pk(R) ); + send_2(R,I, ni ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as-cj.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as-cj.spdl new file mode 100644 index 0000000..b393294 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as-cj.spdl @@ -0,0 +1,66 @@ +# Clark and Jacob modified Hwang and Chen modified SPLICE/AS +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/spliceas3.html +# +# Note: +# The assumptions made here do not comply with those in SPORE +# SPORE assumes that the agents do not know the pk function, but only +# their own public key values. +# This can currently not be modelled. + + +usertype TimeStamp, LifeTime; + +const inc,dec: Function; +inversekeys (inc,dec); + +protocol spliceAS-CJ(I,R,S) +{ + role I + { + fresh N1,N2: Nonce; + fresh T: TimeStamp; + fresh L: LifeTime; + + send_1(I,S, I, R, N1 ); + recv_2(S,I, S, {S, I, N1, R, pk(R)}sk(S) ); + send_3(I,R, I, R, {T, L, {I, N2}pk(R)}sk(I) ); + recv_6(R,I, R, I, {{N2}inc}pk(I) ); + + claim_7(I, Secret, N2); + claim_9(I, Niagree); + claim_10(I, Nisynch); + } + + role S + { + var N1,N3: Nonce; + + recv_1(I,S, I, R, N1 ); + send_2(S,I, S, {S, I, N1, R, pk(R)}sk(S) ); + recv_4(R,S, R, I, N3 ); + send_5(S,R, S, {S, R, N3, pk(I)}sk(S) ); + } + + role R + { + fresh N3: Nonce; + var N2: Nonce; + var T: TimeStamp; + var L: LifeTime; + + var ni: Nonce; + fresh nr: Nonce; + + recv_3(I,R, I, R, {T, L, {I, N2}pk(R)}sk(I) ); + send_4(R,S, R, I, N3 ); + recv_5(S,R, S, {S, R, N3, pk(I)}sk(S) ); + send_6(R,I, R, I, {{N2}inc}pk(I) ); + + claim_8(R, Secret, N2); + claim_11(R, Niagree); + claim_12(R, Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as-hc.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as-hc.spdl new file mode 100644 index 0000000..2f975ad --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as-hc.spdl @@ -0,0 +1,61 @@ +# Hwang and Chen Modified SPLICE/AS +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/spliceas2.html +# + + +usertype TimeStamp, LifeTime; + +const inc,dec: Function; +inversekeys (inc,dec); + +protocol spliceAS-HC(I,R,S) +{ + role I + { + fresh N1,N2: Nonce; + fresh T: TimeStamp; + fresh L: LifeTime; + + send_1(I,S, I, R, N1 ); + recv_2(S,I, S, {S, I, N1, R, pk(R)}sk(S) ); + send_3(I,R, I, R, {I, T, L, {N2}pk(R)}sk(I) ); + recv_6(R,I, R, I, {R, {N2}inc}pk(I) ); + + claim_7(I, Secret, N2); + claim_9(I, Niagree); + claim_10(I, Nisynch); + } + + role S + { + var N1,N3: Nonce; + + recv_1(I,S, I, R, N1 ); + send_2(S,I, S, {S, I, N1, R, pk(R)}sk(S) ); + recv_4(R,S, R, I, N3 ); + send_5(S,R, S, {S, R, N3, I, pk(I)}sk(S) ); + } + + role R + { + fresh N3: Nonce; + var N2: Nonce; + var T: TimeStamp; + var L: LifeTime; + + var ni: Nonce; + fresh nr: Nonce; + + recv_3(I,R, I, R, {I, T, L, {N2}pk(R)}sk(I) ); + send_4(R,S, R, I, N3 ); + recv_5(S,R, S, {S, R, N3, I, pk(I)}sk(S) ); + send_6(R,I, R, I, {R, {N2}inc}pk(I) ); + + claim_8(R, Secret, N2); + claim_11(R, Niagree); + claim_12(R, Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as.spdl new file mode 100644 index 0000000..b1d8e18 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/splice-as.spdl @@ -0,0 +1,66 @@ +# SPLICE/AS +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/spliceas.html +# +# Note: +# The assumptions made here do not comply with those in SPORE +# SPORE assumes that the agents do not know the pk function, but only +# their own public key values. +# This can currently not be modelled. + + +usertype TimeStamp, LifeTime; + +const inc,dec: Function; +inversekeys (inc,dec); + +protocol spliceAS(I,R,S) +{ + role I + { + fresh N1,N2: Nonce; + fresh T: TimeStamp; + fresh L: LifeTime; + + send_1(I,S, I, R, N1 ); + recv_2(S,I, S, {S, I, N1, pk(R)}sk(S) ); + send_3(I,R, I, R, {I, T, L, {N2}pk(R)}sk(I) ); + recv_6(R,I, R, I, {R, {N2}inc}pk(I) ); + + claim_7(I, Secret, N2); + claim_9(I, Niagree); + claim_10(I, Nisynch); + } + + role S + { + var N1,N3: Nonce; + + recv_1(I,S, I, R, N1 ); + send_2(S,I, S, {S, I, N1, pk(R)}sk(S) ); + recv_4(R,S, R, I, N3 ); + send_5(S,R, S, {S, R, N3, pk(I)}sk(S) ); + } + + role R + { + fresh N3: Nonce; + var N2: Nonce; + var T: TimeStamp; + var L: LifeTime; + + var ni: Nonce; + fresh nr: Nonce; + + recv_3(I,R, I, R, {I, T, L, {N2}pk(R)}sk(I) ); + send_4(R,S, R, I, N3 ); + recv_5(S,R, S, {S, R, N3, pk(I)}sk(S) ); + send_6(R,I, R, I, {R, {N2}inc}pk(I) ); + + claim_8(R, Secret, N2); + claim_11(R, Niagree); + claim_12(R, Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/tmn.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/tmn.spdl new file mode 100644 index 0000000..c6fb55f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/tmn.spdl @@ -0,0 +1,51 @@ +# TMN +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/tmn.html +# +# Note: +# According to Boyd and Mathuria Kb is the session key this is not clear +# from the description in SPORE +usertype SessionKey; + +const Fresh: Function; +const Compromised: Function; + +protocol tmn(I,R,S) +{ + role I + { + fresh Ki: SessionKey; + var Kr: SessionKey; + + send_1(I,S, R,{Ki}pk(S) ); + recv_4(S,I, R,{Kr}Ki ); + + claim_I1(I,Secret,Kr); + claim_I2(I,Nisynch); + claim_I3(I,Empty,(Fresh,Kr)); + } + + role R + { + fresh Kr: SessionKey; + + recv_2(S,R, I ); + send_3(R,S, I, { Kr }pk(S) ); + + claim_R1(R,Secret,Kr); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,Kr)); + } + + role S + { + var Ki,Kr: SessionKey; + + recv_1(I,S, R,{Ki}pk(S) ); + send_2(S,R, I ); + recv_3(R,S, I, { Kr }pk(S) ); + send_4(S,I, R,{Kr}Ki ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf-brutus.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf-brutus.spdl new file mode 100644 index 0000000..c22bdcc --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf-brutus.spdl @@ -0,0 +1,32 @@ +usertype SesKey, Server; + +/* Version from the Brutus reports +*/ + +protocol wmfbrutus(A,B,S) +{ + role A + { + fresh kab : SesKey; + + send_1(A,S, A, { B,kab }k(A,S) ); + } + + role B + { + var kab : SesKey; + + recv_2(S,B, { A, kab }k(B,S) ); + + claim_3(B, Secret,kab); + } + + role S + { + var kab : SesKey; + + recv_1(A,S, A, { B,kab }k(A,S) ); + send_2(S,B, { A, kab }k(B,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf-lowe.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf-lowe.spdl new file mode 100644 index 0000000..0e0de87 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf-lowe.spdl @@ -0,0 +1,63 @@ +# Lowe modified Wide Mouthed Frog +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wideMouthedFrogLowe.html +# +# Note: +# According to SPORE there are no known attacks on this protocol, scyther +# finds one however this has to do with the unusual assumption that every +# agent can recognise and will reject to recv messages that it has created +# itself. + +usertype SessionKey; +usertype TimeStamp; +usertype ExpiredTimeStamp; +const succ,pred: Function; +inversekeys (succ,pred); +const Fresh: Function; +const Compromised: Function; + +protocol wmf-Lowe(I,R,S) +{ + role I + { + fresh Kir: SessionKey; + fresh Ti: TimeStamp; + var Kr: SessionKey; + var Nr: Nonce; + + send_1(I,S, I, {Ti, R, Kir}k(I,S)); + recv_3(R,I,{Nr}Kir); + send_4(I,R,{{Nr}succ}Kir); + + claim_I1(I,Secret,Kir); + claim_I2(I,Nisynch); + claim_I3(I,Empty,(Fresh,Kir)); + } + + role R + { + var Ts: TimeStamp; + var Kir: SessionKey; + fresh Nr: Nonce; + + recv_2(S,R, {Ts, I, Kir}k(R,S) ); + send_3(R,I, {Nr}Kir); + recv_4(I,R, {{Nr}succ}Kir); + + claim_R1(R,Secret,Kir); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,Kir)); + } + + role S + { + var Kir: SessionKey; + fresh Ts: TimeStamp; + var Ti: TimeStamp; + + recv_1(I,S, I,{Ti, R, Kir}k(I,S) ); + send_2(S,R, {Ts, I, Kir}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf.spdl new file mode 100644 index 0000000..758843a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/wmf.spdl @@ -0,0 +1,54 @@ +# Wide Mouthed Frog +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wideMouthedFrog.html +# +# Note +# The name of the party that has generated a message was added in order +# to model the property described in SPORE that an agent can identify +# its own messages and will reject them. + +usertype SessionKey; +usertype TimeStamp; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + +protocol wmf(I,R,S) +{ + role I + { + fresh Kir: SessionKey; + fresh Ti: TimeStamp; + var Kr: SessionKey; + + send_1(I,S, I, {I, Ti, R, Kir}k(I,S)); + + claim_I1(I,Secret,Kir); + claim_I2(I,Empty,(Fresh,Kir)); + } + + role R + { + var Ts: TimeStamp; + var Kir: SessionKey; + + recv_2(S,R, {S, Ts, I, Kir}k(R,S) ); + + claim_R1(R,Secret,Kir); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,Kir)); + } + + role S + { + var Kir: SessionKey; + fresh Ts: TimeStamp; + var Ti: TimeStamp; + + recv_1(I,S, I,{I, Ti, R, Kir}k(I,S) ); + send_2(S,R, {S, Ts, I, Kir}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-1.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-1.spdl new file mode 100644 index 0000000..7e4e09d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-1.spdl @@ -0,0 +1,41 @@ +# Woo and Lam Pi 1 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPi1.html +# + +protocol woolamPi-1(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {I,R,Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I,R, T}k(R,S)); + recv_5(S,R, {I,R, Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I,R, {I,R,Nr}k(I,S)}k(R,S)); + send_5(S,R, {I,R,Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-2.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-2.spdl new file mode 100644 index 0000000..5d767d6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-2.spdl @@ -0,0 +1,41 @@ +# Woo and Lam Pi 2 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPi2.html +# + +protocol woolamPi-2(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {I,Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I, T}k(R,S)); + recv_5(S,R, {I, Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I, {I,Nr}k(I,S)}k(R,S)); + send_5(S,R, {I,Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-3.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-3.spdl new file mode 100644 index 0000000..1db544e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-3.spdl @@ -0,0 +1,41 @@ +# Woo and Lam Pi 2 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPi3.html +# + +protocol woolamPi-3(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I, T}k(R,S)); + recv_5(S,R, {I, Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I, {Nr}k(I,S)}k(R,S)); + send_5(S,R, {I,Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-f.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-f.spdl new file mode 100644 index 0000000..22f028c --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam-pi-f.spdl @@ -0,0 +1,41 @@ +# Woo and Lam Pi f +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPif.html +# + +protocol woolamPi-f(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {I,R,Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I, R, Nr, T}k(R,S)); + recv_5(S,R, {I, R, Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I, R, Nr,{I,R,Nr}k(I,S)}k(R,S)); + send_5(S,R, {I, R, Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam.spdl new file mode 100644 index 0000000..7e28057 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/woo-lam.spdl @@ -0,0 +1,64 @@ +# Woo and Lam Mutual Authentication +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamMutual.html +# + + +usertype SessionKey; + +const Fresh: Function; +const Compromised: Function; + +protocol woolam(I,R,S) +{ + role I + { + fresh N1: Nonce; + var Kir: SessionKey; + var N2: Nonce; + + send_1(I,R, I, N1); + recv_2(R,I, R, N2); + send_3(I,R, {I, R, N1, N2}k(I,S)); + recv_6(R,I, {R, N1, N2, Kir}k(I,S), {N1,N2}Kir); + send_7(I,R, {N2}Kir); + + + claim_I1(I,Secret,Kir); + claim_I2(I,Nisynch); + claim_I3(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh N2: Nonce; + var N1: Nonce; + var Kir: SessionKey; + var T1,T2: Ticket; + + recv_1(I,R, I, N1); + send_2(R,I, R, N2); + recv_3(I,R, T1); + send_4(R,S, T1, {I, R, N1, N2}k(R,S)); + recv_5(S,R, T2, {I, N1, N2, Kir}k(R,S)); + send_6(R,I, T2, {N1,N2}Kir); + recv_7(I,R, {N2}Kir); + + claim_R1(R,Secret,Kir); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,Kir)); + } + + role S + { + fresh Kir: SessionKey; + var N1,N2: Nonce; + + recv_4(R,S, {I, R, N1, N2}k(I,S), {I, R, N1, N2}k(R,S)); + send_5(S,R, {R, N1, N2, Kir}k(I,S), {I, N1, N2, Kir}k(R,S)); + } +} + + + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban-paulson-modified.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban-paulson-modified.spdl new file mode 100644 index 0000000..13d62a6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban-paulson-modified.spdl @@ -0,0 +1,49 @@ +// BAN modified version of the yahalom protocol +// +// Modeled as version in Paulson's paper: +// "Relations Between Secrets: Two Formal Analyses of the Yahalom +// Protocol" +// +// Modified (improved) version from page 16. + +usertype Server; +usertype SessionKey; + +protocol yahalom-BAN-Paulson-modified(A,B,S) +{ + role A + { + fresh na: Nonce; + var nb: Nonce; + var ticket: Ticket; + var kab: SessionKey; + + send_1(A,B, A,na); + recv_3(S,A, nb, {B,kab,na}k(A,S), ticket ); + send_4(A,B, ticket, {nb}kab ); + claim_5(A, Secret,kab); + } + + role B + { + fresh nb: Nonce; + var na: Nonce; + var ticket: Ticket; + var kab: SessionKey; + + recv_1(A,B, A,na); + send_2(B,S, B, nb, {A,na}k(B,S) ); + recv_4(A,B, {A,B,kab,nb}k(B,S) , {nb}kab ); + claim_6(B, Secret,kab); + } + + role S + { + fresh kab: SessionKey; + var na,nb: Nonce; + + recv_2(B,S, B, nb, {A,na}k(B,S) ); + send_3(S,A, nb, {B,kab,na}k(A,S), {A,B,kab,nb}k(B,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban-paulson.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban-paulson.spdl new file mode 100644 index 0000000..7d312ec --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban-paulson.spdl @@ -0,0 +1,47 @@ +// BAN modified version of the yahalom protocol +// +// Modeled as version in Paulson's paper: +// "Relations Between Secrets: Two Formal Analyses of the Yahalom +// Protocol" + +usertype Server; +usertype SessionKey; + +protocol yahalom-BAN-Paulson(A,B,S) +{ + role A + { + fresh na: Nonce; + var nb: Nonce; + var ticket: Ticket; + var kab: SessionKey; + + send_1(A,B, A,na); + recv_3(S,A, {B,kab,na,nb}k(A,S), ticket ); + send_4(A,B, ticket, {nb}kab ); + claim_5(A, Secret,kab); + } + + role B + { + fresh nb: Nonce; + var na: Nonce; + var ticket: Ticket; + var kab: SessionKey; + + recv_1(A,B, A,na); + send_2(B,S, B, {A,na,nb}k(B,S) ); + recv_4(A,B, {A,kab}k(B,S) , {nb}kab ); + claim_6(B, Secret,kab); + } + + role S + { + fresh kab: SessionKey; + var na,nb: Nonce; + + recv_2(B,S, B, {A,na,nb}k(B,S) ); + send_3(S,A, {B,kab,na,nb}k(A,S), {A,kab}k(B,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban.spdl new file mode 100644 index 0000000..3fa5f84 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-ban.spdl @@ -0,0 +1,55 @@ +# BAN simplified version of Yahalom +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/yahalomBAN.html +# + +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol yahalom-BAN(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Kir: SessionKey; + + send_1(I,R, I,Ni); + recv_3(S,I, Nr, {R,Kir,Ni}k(I,S), T ); + send_4(I,R, T, {Nr}Kir ); + + claim_I1(I, Secret,Kir); + claim_I2(I, Nisynch); + claim_I3(I, Empty, (Fresh,Kir)); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + var T: Ticket; + var Kir: SessionKey; + + recv_1(I,R, I,Ni); + send_2(R,S, R, Nr, {I,Ni}k(R,S) ); + recv_4(I,R, {I,Kir,Nr}k(R,S) , {Nr}Kir ); + + claim_R1(R, Secret,Kir); + claim_R2(R, Nisynch); + claim_R3(R, Empty, (Fresh,Kir)); + } + + role S + { + fresh Kir: SessionKey; + var Ni,Nr: Nonce; + + recv_2(R,S, R, Nr, {I,Ni}k(R,S) ); + send_3(S,I, Nr, {R,Kir,Ni}k(I,S), {I,Kir,Nr}k(R,S) ); + } +} + + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-lowe.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-lowe.spdl new file mode 100644 index 0000000..651389d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom-lowe.spdl @@ -0,0 +1,53 @@ +# Lowe's modified version of Yahalom +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/yahalomLowe.html +# +# + +usertype SessionKey; + + +protocol yahalom-Lowe(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var Kir: SessionKey; + + send_1(I,R, I,Ni); + recv_3(S,I, {R,Kir,Ni,Nr}k(I,S) ); + send_5(I,R, {I, R, S, Nr}Kir ); + + claim_I1(I, Secret,Kir); + claim_I2(I, Nisynch); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + var Kir: SessionKey; + + recv_1(I,R, I,Ni); + send_2(R,S, {I,Ni,Nr}k(R,S) ); + recv_4(S,R, {I,Kir}k(R,S)); + recv_5(I,R, {I, R, S, Nr}Kir); + + claim_R1(R, Secret,Kir); + claim_R2(R, Nisynch); + } + + role S + { + fresh Kir: SessionKey; + var Ni,Nr: Nonce; + + recv_2(R,S, {I,Ni,Nr}k(R,S) ); + send_3(S,I, {R,Kir,Ni,Nr}k(I,S)); + send_4(S,R, {I,Kir}k(R,S)); + } +} + + diff --git a/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom.spdl b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom.spdl new file mode 100644 index 0000000..063817f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/MultiProtocolAttacks/yahalom.spdl @@ -0,0 +1,52 @@ +# Yahalom +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/yahalom.html +# +# + +usertype SessionKey; + +protocol yahalom(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Kir: SessionKey; + + send_1(I,R, I,Ni); + recv_3(S,I, {R,Kir,Ni,Nr}k(I,S), T ); + send_4(I,R, T, {Nr}Kir ); + + claim_I1(I, Secret,Kir); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + var T: Ticket; + var Kir: SessionKey; + + recv_1(I,R, I,Ni); + send_2(R,S, R, {I,Ni,Nr}k(R,S) ); + recv_4(I,R, {I,Kir}k(R,S) , {Nr}Kir ); + + claim_R1(R, Secret,Kir); + } + + role S + { + fresh Kir: SessionKey; + var Ni,Nr: Nonce; + + recv_2(R,S, R, {I,Ni,Nr}k(R,S) ); + send_3(S,I, {R,Kir,Ni,Nr}k(I,S), {I,Kir}k(R,S) ); + + claim(S, Secret, Ni); + claim(S, Secret, Nr); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/NotModelled.txt b/Vagrant Files/files/scyther/Protocols/NotModelled.txt new file mode 100644 index 0000000..120e55f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/NotModelled.txt @@ -0,0 +1,23 @@ +The following protocols have not been modelled for use in Scyther: + +- CAM http://www.lsv.ens-cachan.fr/spore/cam.html +This protocol only consists of one message and corresponding database actions. +The description given in SPORE is unsuitable for formalisation. + +- Diffie Helman http://www.lsv.ens-cachan.fr/spore/diffieHelman.html +This protocol relies on algebraic properties that can not be modelled in +scyther. + +- GJM http://www.lsv.ens-cachan.fr/spore/gjm.html +This protocol contains complicated if-then-else constructions that can +not be modelled in scyther. + +- Gong http://www.lsv.ens-cachan.fr/spore/gong.html +This protocol relies on algebraic properties that can not be modelled in +scyther. + +- SK3 +This protocol relies on algebraic properties that can not be modelled in +scyther. It also has the notion of channels that can not be attacked, +which can not be modelled in scyther either. + diff --git a/Vagrant Files/files/scyther/Protocols/andrew-ban-concrete.spdl b/Vagrant Files/files/scyther/Protocols/andrew-ban-concrete.spdl new file mode 100644 index 0000000..48f52d8 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/andrew-ban-concrete.spdl @@ -0,0 +1,67 @@ +# BAN concrete Andrew Secure RPC +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/andrewBAN2.html +# +# Note: +# The shared key between I and R is modelled as k(I,R) currently +# there is no way to express that this key is equal to k(R,I) +# In order to overcome this a 'dummy' role X has been hadded that recrypts +# a given term crypted with k(I,R) with k(R,I) +# +# Note: +# Recv 4 by the Initatior has been placed after the synchronisation claim +# as it allows trivial synchronisation attacks otherwise (the message is +# completely fresh and can therefore always be replaced by an arbitrary value +# created by the intruder) which are not considered in SPORE +# + +usertype SessionKey; +const Fresh: Function; + +protocol @swapkey(X) +{ + # Protocol added to work around the symmetry problems where k(I,R) != k(R,I) + role X + { + var I,R: Agent; + var T:Ticket; + recv_!X1(X,X,I,R,{T}k(I,R)); + send_!X2(X,X,{T}k(R,I)); + } +} + +protocol andrew-Concrete(I,R) +{ + + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir: SessionKey; + + send_1(I,R, I,ni ); + recv_2(R,I, {ni,kir}k(I,R) ); + send_3(I,R, {ni}kir); + claim_I1(I,Secret,kir); + claim_I2(I,Nisynch); + claim_I3(I,Empty,(Fresh,kir)); + recv_6(R,I, nr); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + fresh kir: SessionKey; + + recv_1(I,R, I,ni ); + send_2(R,I, {ni,kir}k(I,R) ); + recv_3(I,R, {ni}kir); + send_6(R,I, nr); + claim_R1(R,Secret,kir); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,kir)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/andrew-ban.spdl b/Vagrant Files/files/scyther/Protocols/andrew-ban.spdl new file mode 100644 index 0000000..9ebd566 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/andrew-ban.spdl @@ -0,0 +1,54 @@ +# BAN modified Andrew Secure RPC +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/andrewBAN.html +# +# Note: +# The shared key between I and R is modelled as k(I,R) currently +# there is no way to express that this key is equal to k(R,I) +# So it is possile that certain attacks that use this property are not found +# +# Note: +# According to SPORE there are no known attacks on this protocol +# +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol andrew-Ban(I,R) +{ + role I + { + fresh ni: Nonce; + var nr,nr2: Nonce; + var kir: SessionKey; + + send_1(I,R, I,{ni}k(I,R) ); + recv_2(R,I, {ni,nr}k(I,R) ); + send_3(I,R, {nr}k(I,R) ); + recv_4(R,I, {kir,nr2,ni}k(I,R) ); + claim_I1(I,Nisynch); + claim_I2(I,Niagree); + claim_I3(I,Secret, kir); + claim_I4(I,Secret, k(I,R)); + claim_I5(I,Empty, (Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr,nr2: Nonce; + fresh kir: SessionKey; + + recv_1(I,R, I,{ni}k(I,R) ); + send_2(R,I, {ni,nr}k(I,R) ); + recv_3(I,R, {nr}k(I,R) ); + send_4(R,I, {kir,nr2,ni}k(I,R) ); + claim_R1(R,Nisynch); + claim_R2(R,Niagree); + claim_R3(R,Secret, kir); + claim_R4(R,Secret, k(I,R)); + claim_R5(R,Empty, (Fresh,kir)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/andrew-lowe-ban.spdl b/Vagrant Files/files/scyther/Protocols/andrew-lowe-ban.spdl new file mode 100644 index 0000000..04e15f2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/andrew-lowe-ban.spdl @@ -0,0 +1,57 @@ +# Lowe modified BAN concrete Andrew Secure RPC +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/andrewLowe.html +# +# Note: +# The shared key between I and R is modelled as k(I,R) currently +# there is no way to express that this key is equal to k(R,I) +# So it is possile that certain attacks that use this property are not found +# +# Note: +# Recv 4 by the Initatior has been placed after the synchronisation claim +# as it allows trivial synchronisation attacks otherwise (the message is +# completely fresh and can therefore always be replaced by an arbitrary value +# created by the intruder) which are not considered in SPORE +# +# Note: +# According to SPORE there are no known attacks on this protocol +# + +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol andrew-LoweBan(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir: SessionKey; + + send_1(I,R, I,ni ); + recv_2(R,I, {ni,kir,R}k(I,R) ); + send_3(I,R, {ni}kir ); + claim_I1(I,Nisynch); + claim_I2(I,Secret, kir); + claim_I3(I,Empty, (Fresh,kir)); + recv_4(R,I, nr ); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + fresh kir: SessionKey; + + recv_1(I,R, I,ni ); + send_2(R,I, {ni,kir,R}k(I,R) ); + recv_3(I,R, {ni}kir ); + send_4(R,I, nr ); + claim_R1(R,Nisynch); + claim_R2(R,Secret, kir); + claim_R3(R,Empty, (Fresh,kir)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/andrew.spdl b/Vagrant Files/files/scyther/Protocols/andrew.spdl new file mode 100644 index 0000000..b2e663c --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/andrew.spdl @@ -0,0 +1,50 @@ +# Andrew Secure RPC +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/andrew.html +# +# Note: +# The shared key between I and R is modelled as k(I,R) currently +# there is no way to express that this key is equal to k(R,I) +# So it is possile that certain attacks that use this property are not found +# + +usertype SessionKey; +const succ: Function; +const Fresh: Function; + +protocol andrew(I,R) +{ + role I + { + fresh ni: Nonce; + var nr,nr2: Nonce; + var kir: SessionKey; + + send_1(I,R, I,{ni}k(I,R) ); + recv_2(R,I, {succ(ni),nr}k(I,R) ); + send_3(I,R, {succ(nr)}k(I,R) ); + recv_4(R,I, {kir,nr2}k(I,R) ); + claim_I1(I,Secret,kir); + claim_I2(I,Nisynch); + claim_I3(I,Niagree); + claim_I4(I,Empty,(Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr,nr2: Nonce; + fresh kir: SessionKey; + + recv_1(I,R, I,{ni}k(I,R) ); + send_2(R,I, {succ(ni),nr}k(I,R) ); + recv_3(I,R, {succ(nr)}k(I,R) ); + send_4(R,I, {kir,nr2}k(I,R) ); + claim_R1(R,Secret,kir); + claim_R2(R,Nisynch); + claim_R3(R,Niagree); + claim_R4(R,Empty,(Fresh,kir)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ccitt509-1.spdl b/Vagrant Files/files/scyther/Protocols/ccitt509-1.spdl new file mode 100644 index 0000000..29c665a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ccitt509-1.spdl @@ -0,0 +1,35 @@ +# CCITT X.509 (1) +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/ccittx509_1.html +# +# Note: +# The attack in SPORE is not found as this is not an attack against +# synchronisation, but an attack against the freshness of Xa and Ya +# which can currently not be modelled in scyther +# + +usertype Timestamp; + +protocol ccitt509-1(I,R) +{ + role I + { + fresh Ta: Timestamp; + fresh Na,Xa,Ya: Nonce; + send_1(I,R, I,{Ta, Na, R, Xa,{Ya}pk(R)}sk(I)); + # claim_2(I,Nisynch); + # This claim is useless as there are no preceding recv events + } + + role R + { + var Ta: Timestamp; + var Na,Xa,Ya: Nonce; + + recv_1(I,R, I,{Ta, Na, R, Xa,{Ya}pk(R)}sk(I)); + claim_3(R,Nisynch); + # There should also be Fresh Xa and Fresh Ya claims here + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ccitt509-1c.spdl b/Vagrant Files/files/scyther/Protocols/ccitt509-1c.spdl new file mode 100644 index 0000000..b75e069 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ccitt509-1c.spdl @@ -0,0 +1,34 @@ +# CCITT X.509 (1c) +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/ccittx509_1c.html +# +# Note: +# According to SPORE there are no known attacks on this protocol +# + +hashfunction hash; +usertype Timestamp; + +protocol ccitt509-1c(I,R) +{ + role I + { + fresh Ta: Timestamp; + fresh Na,Xa,Ya: Nonce; + send_1(I,R, I,{Ta, Na, R, Xa,{Ya,{hash(Ya)}sk(I)}pk(R)}sk(I)); + # claim_2(I,Nisynch); + # This claim is useless as there are no preceding receive events + } + + role R + { + var Ta: Timestamp; + var Na,Xa,Ya: Nonce; + + recv_1(I,R, I,{Ta, Na, R, Xa,{Ya,{hash(Ya)}sk(I)}pk(R)}sk(I)); + claim_3(R,Nisynch); + # There should also be Fresh Xa and Fresh Ya claims here + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ccitt509-3.spdl b/Vagrant Files/files/scyther/Protocols/ccitt509-3.spdl new file mode 100644 index 0000000..9ad1d3f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ccitt509-3.spdl @@ -0,0 +1,45 @@ +# CCITT X.509 (3) +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/ccittx509_3.html +# +# Note: +# The protocol description also states that Xa and Ya should be fresh +# this can not be verified using scyther +# + +usertype Timestamp; + +protocol ccitt509-3(I,R) +{ + role I + { + fresh Ta: Timestamp; + var Tb: Timestamp; + fresh Na,Xa,Ya: Nonce; + var Xb,Nb,Yb: Nonce; + send_1(I,R, I,{Ta, Na, R, Xa,{Ya}pk(R)}sk(I)); + recv_2(R,I, R,{Tb, Nb, I, Na, Xb,{Yb}pk(I)}sk(R)); + send_3(I,R, I, {Nb}sk(I)); + claim_I1(I,Nisynch); + claim_I2(I,Secret,Ya); + claim_I3(I,Secret,Yb); + } + + role R + { + var Ta: Timestamp; + fresh Tb: Timestamp; + var Na,Xa,Ya: Nonce; + fresh Xb,Yb,Nb: Nonce; + + recv_1(I,R, I,{Ta, Na, R, Xa,{Ya}pk(R)}sk(I)); + send_2(R,I, R,{Tb, Nb, I, Na, Xb,{Yb}pk(I)}sk(R)); + recv_3(I,R, I, {Nb}sk(I)); + claim_R1(R,Nisynch); + claim_R2(R,Secret,Ya); + claim_R3(R,Secret,Yb); + # There should also be Fresh Xa and Fresh Ya claims here + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ccitt509-ban3.spdl b/Vagrant Files/files/scyther/Protocols/ccitt509-ban3.spdl new file mode 100644 index 0000000..bdf146d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ccitt509-ban3.spdl @@ -0,0 +1,39 @@ +# BAN modified version of CCITT X.509 (3) +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/ccittx509_3BAN.html +# +# Note: +# The protocol description also states that Xa and Ya should be fresh +# this can not be verified using scyther +# +# Note: +# According to SPORE there are no known attacks on this protocol +# + +protocol ccitt509-ban3(I,R) +{ + role I + { + fresh Na,Xa,Ya: Nonce; + var Xb,Nb,Yb: Nonce; + + send_1(I,R, I,{Na, R, Xa,{Ya}pk(R)}sk(I)); + recv_2(R,I, R,{Nb, I, Na, Xb,{Yb}pk(I)}sk(R)); + send_3(I,R, I,{R, Nb}sk(I)); + claim_4(I,Nisynch); + } + + role R + { + var Na,Xa,Ya: Nonce; + fresh Xb,Yb,Nb: Nonce; + + recv_1(I,R, I,{Na, R, Xa,{Ya}pk(R)}sk(I)); + send_2(R,I, R,{Nb, I, Na, Xb,{Yb}pk(I)}sk(R)); + recv_3(I,R, I,{R, Nb}sk(I)); + claim_5(R,Nisynch); + # There should also be Fresh Xa and Fresh Ya claims here + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/denning-sacco-lowe.spdl b/Vagrant Files/files/scyther/Protocols/denning-sacco-lowe.spdl new file mode 100644 index 0000000..761c22b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/denning-sacco-lowe.spdl @@ -0,0 +1,67 @@ +# Lowe modified Denning-Sacco shared key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/denningSaccoLowe.html +# +# Note: +# According to SPORE there are no attacks on this protocol. Scyther +# finds a straightforward pre-play attack on the first message, which +# violates synchronisation. However, this does not seem to be a +# practical attack unless consistency is required, e.g., for logging or +# auditing. + +usertype Key; +usertype SessionKey; +usertype TimeStamp; +usertype ExpiredTimeStamp; +usertype PseudoFunction; +const dec: PseudoFunction; +const Fresh: Function; +const Compromised: Function; + +protocol denningSacco-Lowe(I,R,S) +{ + role I + { + var W: Ticket; + var Kir: SessionKey; + var T: TimeStamp; + var Nr: Nonce; + + send_1(I,S, I,R ); + recv_2(S,I, {R, Kir, T, W}k(I,S) ); + send_3(I,R, W); + recv_4(R,I, {Nr}Kir); + send_5(I,R, {{Nr}dec}Kir); + claim_I1(I,Niagree); + claim_I2(I,Nisynch); + claim_I3(I,SKR,Kir); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + var Kir: SessionKey; + var T: TimeStamp; + fresh Nr: Nonce; + + recv_3(I,R, {Kir,I,T}k(R,S)); + send_4(R,I, {Nr}Kir); + recv_5(I,R, {{Nr}dec}Kir); + claim_R1(R,Niagree); + claim_R2(R,Nisynch); + claim_R3(R,Secret,Kir); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var W: Ticket; + fresh Kir: SessionKey; + fresh T: TimeStamp; + + recv_1(I,S, I,R ); + send_2(S,I, {R, Kir, T, {Kir, I,T}k(R,S)}k(I,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/denning-sacco.spdl b/Vagrant Files/files/scyther/Protocols/denning-sacco.spdl new file mode 100644 index 0000000..d77402f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/denning-sacco.spdl @@ -0,0 +1,53 @@ +# Denning-Sacco shared key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/denningSacco.html +# + +usertype Key; +usertype SessionKey; +usertype TimeStamp; +usertype ExpiredTimeStamp; +const Fresh: Function; +const Compromised: Function; + +protocol denningSacco(I,R,S) +{ + role I + { + var W: Ticket; + var Kir: SessionKey; + var T: TimeStamp; + + send_1(I,S, I,R ); + recv_2(S,I, {R, Kir, T, W}k(I,S) ); + send_3(I,R, W); + claim_I1(I,Niagree); + claim_I2(I,Nisynch); + claim_I3(I,Secret,Kir); + claim_I4(I,Empty, (Fresh,Kir)); + } + + role R + { + var Kir: SessionKey; + var T: TimeStamp; + + recv_3(I,R, {Kir,I,T}k(R,S)); + claim_R1(R,Niagree); + claim_R2(R,Nisynch); + claim_R3(R,Secret,Kir); + claim_R4(R,Empty, (Fresh,Kir)); + } + + role S + { + var W: Ticket; + fresh Kir: SessionKey; + fresh T: TimeStamp; + + recv_1(I,S, I,R ); + send_2(S,I, {R, Kir, T, {Kir, I,T}k(R,S)}k(I,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/kaochow-v2.spdl b/Vagrant Files/files/scyther/Protocols/kaochow-v2.spdl new file mode 100644 index 0000000..638a54b --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/kaochow-v2.spdl @@ -0,0 +1,55 @@ +# Kao Chow Authentication v.2 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/kaoChow2.html +# + +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol kaochow-2(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir,kt: SessionKey; + + send_1 (I,S, I,R,ni); + recv_3 (R,I, R, {I,R,ni,kir,kt}k(I,S), {ni, kir}kt, nr ); + send_4 (I,R, {nr,kir}kt ); + + claim_I1 (I, Nisynch); + claim_I2 (I, Niagree); + claim_I3 (I, Secret, kir); + claim_I4 (I, Empty, (Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + var kir,kt: SessionKey; + var T: Ticket; + + recv_2 (S,R, T, { I,R,ni,kir,kt }k(R,S) ); + send_3 (R,I, R, T, {ni, kir}kt, nr ); + recv_4 (I,R, {nr,kir}kt ); + + claim_R1 (R, Nisynch); + claim_R2 (R, Niagree); + claim_R3 (R, Secret, kir); + claim_R4 (R, Empty, (Fresh,kir)); + } + + role S + { + var ni: Nonce; + fresh kir, kt: SessionKey; + + recv_1 (I,S, I,R,ni); + send_2 (S,R, {I,R,ni,kir,kt}k(I,S), { I,R,ni,kir,kt }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/kaochow-v3.spdl b/Vagrant Files/files/scyther/Protocols/kaochow-v3.spdl new file mode 100644 index 0000000..88cef24 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/kaochow-v3.spdl @@ -0,0 +1,59 @@ +# Kao Chow Authentication v.3 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/kaoChow3.html +# + +usertype SessionKey; +usertype ExpiredTimeStamp; +usertype TimeStamp; +const Fresh: Function; +const Compromised: Function; + +protocol kaochow-3(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir,kt: SessionKey; + var T2: Ticket; + + send_1 (I,S, I,R,ni); + recv_3 (R,I, {I,R,ni,kir,kt}k(I,S), {ni, kir}kt, nr, T2 ); + send_4 (I,R, {nr,kir}kt, T2 ); + + claim_I1 (I, Nisynch); + claim_I2 (I, Niagree); + claim_I3 (I, Secret, kir); + claim_I4 (I, Empty, (Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + var kir,kt: SessionKey; + var T: Ticket; + fresh tr: TimeStamp; + + recv_2 (S,R, T, { I,R,ni,kir,kt }k(R,S) ); + send_3 (R,I, T, {ni, kir}kt, nr, {I,R,tr,kir}k(R,S) ); + recv_4 (I,R, {nr,kir}kt, {I,R,tr,kir}k(R,S) ); + + claim_R1 (R, Nisynch); + claim_R2 (R, Niagree); + claim_R3 (R, Secret, kir); + claim_R4 (R, Empty, (Fresh,kir)); + } + + role S + { + var ni: Nonce; + fresh kir, kt: SessionKey; + + recv_1 (I,S, I,R,ni); + send_2 (S,R, {I,R,ni,kir,kt}k(I,S), { I,R,ni,kir,kt }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/kaochow.spdl b/Vagrant Files/files/scyther/Protocols/kaochow.spdl new file mode 100644 index 0000000..1c6c827 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/kaochow.spdl @@ -0,0 +1,55 @@ +# Kao Chow Authentication v.1 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/kaoChow1.html +# + +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol kaochow(I,R,S) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + var kir: SessionKey; + + send_1 (I,S, I,R,ni); + recv_3 (R,I, {I,R,ni,kir}k(I,S), {ni}kir, nr ); + send_4 (I,R, {nr}kir ); + + claim_I1 (I, Nisynch); + claim_I2 (I, Niagree); + claim_I3 (I, Secret, kir); + claim_I4 (I, Empty, (Fresh,kir)); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + var kir: SessionKey; + var T; + + recv_2 (S,R, T, { I,R,ni,kir }k(R,S) ); + send_3 (R,I, T, {ni}kir, nr ); + recv_4 (I,R, {nr}kir ); + + claim_R1 (R, Nisynch); + claim_R2 (R, Niagree); + claim_R3 (R, Secret, kir); + claim_R4 (R, Empty, (Fresh,kir)); + } + + role S + { + var ni: Nonce; + fresh kir: SessionKey; + + recv_1 (I,S, I,R,ni); + send_2 (S,R, {I,R,ni,kir}k(I,S), { I,R,ni,kir }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ksl-lowe.spdl b/Vagrant Files/files/scyther/Protocols/ksl-lowe.spdl new file mode 100644 index 0000000..29996d8 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ksl-lowe.spdl @@ -0,0 +1,73 @@ +# Lowe modified KSL +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/kslLowe.html +# +# Note: +# According to SPORE there are no attacks on this protocol, scyther +# finds one however. This has to be investigated further. + +usertype Server, SessionKey, TimeStamp, TicketKey; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + +protocol ksl-Lowe(I,R,S) +{ + role I + { + fresh Ni, Mi: Nonce; + var Nc, Mr: Nonce; + var T: Ticket; + var Kir: SessionKey; + + send_1(I,R, Ni, I); + recv_4(R,I, { Ni,R,Kir }k(I,S), T, Nc, {R,Ni}Kir ); + send_5(I,R, { Nc }Kir ); + + send_6(I,R, Mi,T ); + recv_7(R,I, Mr,{Mi, R}Kir ); + send_8(I,R, {I,Mr}Kir ); + + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty, (Fresh,Kir)); + } + + role R + { + var Ni,Mi: Nonce; + fresh Nr,Nc,Mr: Nonce; + var Kir: SessionKey; + fresh Kbb: TicketKey; + fresh Tr: TimeStamp; + var T: Ticket; + + recv_1(I,R, Ni, I); + send_2(R,S, Ni, I, Nr, R ); + recv_3(S,R, { I, Nr, Kir }k(R,S), T ); + send_4(R,I, T, { Tr, I, Kir }Kbb, Nc, {R, Ni}Kir ); + recv_5(I,R, { Nc }Kir ); + + recv_6(I,R, Mi,{ Tr, I, Kir }Kbb ); + send_7(R,I, Mr,{Mi,R}Kir ); + recv_8(I,R, {I,Mr}Kir ); + + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty, (Fresh,Kir)); + } + + role S + { + var Ni, Nr: Nonce; + fresh Kir: SessionKey; + + recv_2(R,S, Ni, I, Nr, R ); + send_3(S,R, { I, Nr, Kir }k(R,S), { Ni,R,Kir }k(I,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/ksl.spdl b/Vagrant Files/files/scyther/Protocols/ksl.spdl new file mode 100644 index 0000000..7cfca44 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/ksl.spdl @@ -0,0 +1,72 @@ +# KSL +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/ksl.html +# +# + + +usertype Server, SessionKey, TimeStamp, TicketKey; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + +protocol ksl(I,R,S) +{ + role I + { + fresh Ni, Mi: Nonce; + var Nc, Mr: Nonce; + var T: Ticket; + var Kir: SessionKey; + + send_1(I,R, Ni, I); + recv_4(R,I, { Ni,R,Kir }k(I,S), T, Nc, {Ni}Kir ); + send_5(I,R, { Nc }Kir ); + + send_6(I,R, Mi,T ); + recv_7(R,I, Mr,{Mi}Kir ); + send_8(I,R, {Mr}Kir ); + + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty, (Fresh, Kir)); + } + + role R + { + var Ni,Mi: Nonce; + fresh Nr,Nc,Mr: Nonce; + var Kir: SessionKey; + fresh Kbb: TicketKey; + fresh Tr: TimeStamp; + var T: Ticket; + + recv_1(I,R, Ni, I); + send_2(R,S, Ni, I, Nr, R ); + recv_3(S,R, { Nr, I, Kir }k(R,S), T ); + send_4(R,I, T, { Tr, I, Kir }Kbb, Nc, {Ni}Kir ); + recv_5(I,R, { Nc }Kir ); + + recv_6(I,R, Mi,{ Tr, I, Kir }Kbb ); + send_7(R,I, Mr,{Mi}Kir ); + recv_8(I,R, {Mr}Kir ); + + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni, Nr: Nonce; + fresh Kir: SessionKey; + + recv_2(R,S, Ni, I, Nr, R ); + send_3(S,R, { Nr, I, Kir }k(R,S), { Ni,R,Kir }k(I,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/multi-NSL/heuristics-results.txt b/Vagrant Files/files/scyther/Protocols/multi-NSL/heuristics-results.txt new file mode 100644 index 0000000..cc55c31 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/multi-NSL/heuristics-results.txt @@ -0,0 +1,776 @@ +Slave1:multiparty% ./test-heuristics.py +Starting with [11, 15] +Testing using P 3 and 5 runs. +Testing protocol 11. +Heuristic 0: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=0 --timer=20 +states 7488 +attack NoClaim +time 2.007e+01 +st/sec 3.731e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 1: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=1 --timer=20 +states 3869 +attack NoClaim +time 2.004e+01 +st/sec 1.931e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 2: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=2 --timer=20 +states 6543 +attack NoClaim +time 2.006e+01 +st/sec 3.262e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 3: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=3 --timer=20 +states 9003 +attack NoClaim +time 2.005e+01 +st/sec 4.490e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 1 correct: bounded_proof +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 4: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=4 --timer=20 +states 6375 +attack NoClaim +time 2.008e+01 +st/sec 3.175e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 5: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=5 --timer=20 +states 4282 +attack NoClaim +time 2.007e+01 +st/sec 2.134e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 4 correct: bounded_proof time=20 +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 6: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=6 --timer=20 +states 6791 +attack NoClaim +time 2.002e+01 +st/sec 3.392e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 7: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=7 --timer=20 +states 8115 +attack NoClaim +time 2.004e+01 +st/sec 4.049e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 14 correct: bounded_proof time=20 +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 8: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=8 --timer=20 +states 9649 +attack NoClaim +time 2.003e+01 +st/sec 4.817e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 9: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=9 --timer=20 +states 3873 +attack NoClaim +time 2.005e+01 +st/sec 1.932e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 10: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=10 --timer=20 +states 11954 +attack NoClaim +time 2.007e+01 +st/sec 5.956e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 11: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=11 --timer=20 +states 7367 +attack NoClaim +time 2.003e+01 +st/sec 3.678e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 12: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=12 --timer=20 +states 6271 +attack NoClaim +time 2.005e+01 +st/sec 3.128e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 13: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=13 --timer=20 +states 4729 +attack NoClaim +time 2.006e+01 +st/sec 2.357e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 14: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=14 --timer=20 +states 7566 +attack NoClaim +time 2.002e+01 +st/sec 3.779e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 15: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=15 --timer=20 +states 8496 +attack NoClaim +time 2.005e+01 +st/sec 4.237e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 16: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=16 --timer=20 +states 7453 +attack NoClaim +time 2.003e+01 +st/sec 3.721e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 17: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=17 --timer=20 +states 3888 +attack NoClaim +time 2.004e+01 +st/sec 1.940e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 18: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=18 --timer=20 +states 6582 +attack NoClaim +time 2.003e+01 +st/sec 3.286e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 19: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=19 --timer=20 +states 9022 +attack NoClaim +time 2.001e+01 +st/sec 4.509e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 1 correct: bounded_proof +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 20: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=20 --timer=20 +states 6393 +attack NoClaim +time 2.003e+01 +st/sec 3.192e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 21: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=21 --timer=20 +states 4284 +attack NoClaim +time 2.002e+01 +st/sec 2.140e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 4 correct: bounded_proof time=20 +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 22: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=22 --timer=20 +states 6769 +attack NoClaim +time 2.001e+01 +st/sec 3.383e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 23: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=23 --timer=20 +states 8175 +attack NoClaim +time 2.002e+01 +st/sec 4.083e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 14 correct: bounded_proof time=20 +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 24: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=24 --timer=20 +states 9625 +attack NoClaim +time 2.003e+01 +st/sec 4.805e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 25: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=25 --timer=20 +states 3883 +attack NoClaim +time 2.002e+01 +st/sec 1.940e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 26: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=26 --timer=20 +states 11992 +attack NoClaim +time 2.004e+01 +st/sec 5.984e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 27: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=27 --timer=20 +states 7361 +attack NoClaim +time 2.004e+01 +st/sec 3.673e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 28: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=28 --timer=20 +states 6277 +attack NoClaim +time 2.004e+01 +st/sec 3.132e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 29: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=29 --timer=20 +states 4728 +attack NoClaim +time 2.005e+01 +st/sec 2.358e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 30: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=30 --timer=20 +states 7610 +attack NoClaim +time 2.004e+01 +st/sec 3.797e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 31: +./multinsl-generator.py 3 11 | scyther -a -r5 -m2 --summary --goal-select=31 --timer=20 +states 8506 +attack NoClaim +time 2.003e+01 +st/sec 4.247e+02 +claim mnsl3v11 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v11 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v11 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v11 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v11 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Testing protocol 15. +Heuristic 0: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=0 --timer=20 +states 7499 +attack NoClaim +time 2.003e+01 +st/sec 3.744e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 1: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=1 --timer=20 +states 3866 +attack NoClaim +time 2.004e+01 +st/sec 1.929e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 2: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=2 --timer=20 +states 6558 +attack NoClaim +time 2.003e+01 +st/sec 3.274e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 3: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=3 --timer=20 +states 8933 +attack NoClaim +time 2.002e+01 +st/sec 4.462e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 1 correct: bounded_proof +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 4: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=4 --timer=20 +states 6354 +attack NoClaim +time 2.002e+01 +st/sec 3.174e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 5: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=5 --timer=20 +states 4278 +attack NoClaim +time 2.004e+01 +st/sec 2.135e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 4 correct: bounded_proof time=20 +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 6: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=6 --timer=20 +states 6749 +attack NoClaim +time 2.002e+01 +st/sec 3.371e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 7: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=7 --timer=20 +states 8166 +attack NoClaim +time 2.003e+01 +st/sec 4.077e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 14 correct: bounded_proof time=20 +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 8: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=8 --timer=20 +states 9805 +attack NoClaim +time 2.006e+01 +st/sec 4.888e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 9: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=9 --timer=20 +states 3873 +attack NoClaim +time 2.004e+01 +st/sec 1.933e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 10: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=10 --timer=20 +states 10729 +attack NoClaim +time 2.006e+01 +st/sec 5.348e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 11: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=11 --timer=20 +states 6679 +attack NoClaim +time 2.005e+01 +st/sec 3.331e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 12: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=12 --timer=20 +states 6119 +attack NoClaim +time 2.005e+01 +st/sec 3.052e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 13: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=13 --timer=20 +states 3513 +attack NoClaim +time 2.009e+01 +st/sec 1.749e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 14: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=14 --timer=20 +states 7548 +attack NoClaim +time 2.004e+01 +st/sec 3.766e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 15: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=15 --timer=20 +states 8461 +attack NoClaim +time 2.002e+01 +st/sec 4.226e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 16: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=16 --timer=20 +states 7503 +attack NoClaim +time 2.003e+01 +st/sec 3.746e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 17: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=17 --timer=20 +states 3837 +attack NoClaim +time 2.003e+01 +st/sec 1.916e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 18: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=18 --timer=20 +states 6537 +attack NoClaim +time 2.005e+01 +st/sec 3.260e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 19: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=19 --timer=20 +states 8893 +attack NoClaim +time 2.004e+01 +st/sec 4.438e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 1 correct: bounded_proof +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 20: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=20 --timer=20 +states 6325 +attack NoClaim +time 2.003e+01 +st/sec 3.158e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 21: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=21 --timer=20 +states 4253 +attack NoClaim +time 2.005e+01 +st/sec 2.121e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 4 correct: bounded_proof time=20 +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 22: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=22 --timer=20 +states 6756 +attack NoClaim +time 2.004e+01 +st/sec 3.371e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 23: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=23 --timer=20 +states 8149 +attack NoClaim +time 2.003e+01 +st/sec 4.068e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 14 correct: bounded_proof time=20 +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 24: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=24 --timer=20 +states 9785 +attack NoClaim +time 2.004e+01 +st/sec 4.883e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 25: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=25 --timer=20 +states 3832 +attack NoClaim +time 2.006e+01 +st/sec 1.910e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 26: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=26 --timer=20 +states 10699 +attack NoClaim +time 2.009e+01 +st/sec 5.326e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 27: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=27 --timer=20 +states 6672 +attack NoClaim +time 2.006e+01 +st/sec 3.326e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 28: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=28 --timer=20 +states 6136 +attack NoClaim +time 2.010e+01 +st/sec 3.053e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 29: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=29 --timer=20 +states 3521 +attack NoClaim +time 2.009e+01 +st/sec 1.753e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 30: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=30 --timer=20 +states 7584 +attack NoClaim +time 2.006e+01 +st/sec 3.781e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 +Heuristic 31: +./multinsl-generator.py 3 15 | scyther -a -r5 -m2 --summary --goal-select=31 --timer=20 +states 8369 +attack NoClaim +time 2.004e+01 +st/sec 4.176e+02 +claim mnsl3v15 R2V Nisynch_R2b found: 0 correct: does_not_occur +claim mnsl3v15 R2V Secret_R2a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R1V Nisynch_R1b found: 0 correct: does_not_occur +claim mnsl3v15 R1V Secret_R1a found: 1 correct: bounded_proof time=20 +claim mnsl3v15 R0V Nisynch_R0b found: 0 correct: does_not_occur +claim mnsl3v15 R0V Secret_R0a found: 1 correct: bounded_proof time=20 + + +13,25 work well. diff --git a/Vagrant Files/files/scyther/Protocols/multi-NSL/mnsl-results.txt b/Vagrant Files/files/scyther/Protocols/multi-NSL/mnsl-results.txt new file mode 100644 index 0000000..a04a56f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/multi-NSL/mnsl-results.txt @@ -0,0 +1,33 @@ +Report: +------- + +Using P 3 and 2 runs, we find attacks on [1, 5, 9, 13, 18, 22, 26, 30] +Using P 3 and 3 runs, we find attacks on [0, 3, 4, 7, 16, 19, 20, 23] +Using P 3 and 4 runs, we find attacks on [2, 6, 10, 14, 17, 21, 27, 31] +Using P 3 and 5 runs, we find attacks on [25, 29] +Using P 4 and 3 runs, we find attacks on [8, 24] +Using P 4 and 5 runs, we find attacks on [12, 28] + +Log: +---- +Slave1:multiparty% ./test-variants.py +Testing using P 3 and 2 runs. +Using P 3 and 2 runs, we find attacks on [1, 5, 9, 13, 18, 22, 26, 30] +Therefore, we are left with 24 candidates: [0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 17, 19, 20, 21, 23, 24, 25, 27, 28, 29, 31] +Testing using P 3 and 3 runs. +Using P 3 and 3 runs, we find attacks on [0, 3, 4, 7, 16, 19, 20, 23] +Therefore, we are left with 16 candidates: [2, 6, 8, 10, 11, 12, 14, 15, 17, 21, 24, 25, 27, 28, 29, 31] +Testing using P 3 and 4 runs. +Using P 3 and 4 runs, we find attacks on [2, 6, 10, 14, 17, 21, 27, 31] +Therefore, we are left with 8 candidates: [8, 11, 12, 15, 24, 25, 28, 29] +Testing using P 3 and 5 runs. +Using P 3 and 5 runs, we find attacks on [25, 29] +Therefore, we are left with 6 candidates: [8, 11, 12, 15, 24, 28] +Testing using P 4 and 3 runs. +Using P 4 and 3 runs, we find attacks on [8, 24] +Therefore, we are left with 4 candidates: [11, 12, 15, 28] +Testing using P 4 and 4 runs. +Testing using P 4 and 5 runs. +Using P 4 and 5 runs, we find attacks on [12, 28] +Therefore, we are left with 2 candidates: [11, 15] +Testing using P 4 and 6 runs. diff --git a/Vagrant Files/files/scyther/Protocols/multi-NSL/multinsl-generator.py b/Vagrant Files/files/scyther/Protocols/multi-NSL/multinsl-generator.py new file mode 100644 index 0000000..ad44870 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/multi-NSL/multinsl-generator.py @@ -0,0 +1,345 @@ +#!/usr/bin/python +# +# Generate Multi-party NSL protocol description for n parties +# +# Input: P variant +# +# variant uses some bits: +# bit mask meaning if set to '1' +# (message type 1) +# 0 1 nonces in reverse +# 1 2 nonces after agents +# 2 4 agents in reverse +# 3 8 interleaved variant +# (message type 2) +# 4 16 nonces in reverse in message 2 +# +# Convention similar to e.g. Prolog: capitals indicate open variables; +# in particular, they can be bound by _any_ value during the run, +# assuming full type flaws. +# +import sys +from optparse import OptionParser + +def parseArgs(): + usage = "usage: %s [opts] Parties Variant" % sys.argv[0] + parser = OptionParser(usage=usage) + parser.add_option('-p','--protocol', dest='protocol', + help='Generate another protocol [nsl,bke]', default="nsl", + action='store') + (opts, args) = parser.parse_args() + if len(args) != 2: + parser.print_help() + sys.exit(0) + if opts.protocol not in ["nsl","bke","nsl-priv-noprop","nsl-pub-nap","bke-nap"]: + print "I don't know the %s protocol." % (opts.protocol) + sys.exit(0) + return (opts,args) + + +def variablerole (r, inrole): + if r == inrole or inrole == 0: + return False + else: + return True + +def role (r,inrole): + global P + + return "r%i" % (r % P) + +def zeroconst (): + + """ This is 0 or some other stupid constant """ + + return "zeroconst" + +def nonce (r,inrole): + global P + + if r == inrole: + # nonce of our own + return "n%i" % (r % P) + else: + # a variable: we want to see this in the notation + return "N%i" % (r % P) + +def extend (s1, s2): + if s1 == "": + return s2 + else: + return s1 + "," + s2 + +def weavel (l1,l2,reverse1,swap,reverse2,interleave): + """ l1 is typically a list of nonces, l2 might be empty (names) """ + global variant + + if reverse1: + l1.reverse() + if l2 == []: + return l1 + else: + if reverse2: + l2.reverse() + if swap: + # swap + l3 = l1 + l1 = l2 + l2 = l3 + if interleave: + rl = [] + largest = max(len(l1),len(l2)) + for i in range (0,largest): + if i < len(l1): + rl.append(l1[i]) + if i < len(l2): + rl.append(l2[i]) + return rl + else: + return l1 + l2 + +def message1 (label,inrole): + global P,variant,opts + + if opts.protocol in ['bke','nsl']: + noncelist = [] + for i in range(0,label+1): + noncelist.append(nonce(i,inrole)) + rolelist = [] + for i in range(0,P): + if i != (label+1) % P: + rolelist.append(role(i,inrole)) + + return ",".join(weavel(noncelist,rolelist, + (variant & 1 != 0), + (variant & 2 != 0), + (variant & 4 != 0), + (variant & 8 != 0) + )) + elif opts.protocol == 'nsl-priv-noprop': + + list = [] + for i in range(0,P): + list.append(role(i,inrole)) + list.append(nonce(0,inrole)) + msg = ",".join(list) + + for i in range(1,label+1): + msg = "{ %s,%s }sk(%s)" % (msg,nonce(i,inrole),role(i,inrole)) + + return msg + + elif opts.protocol == 'nsl-pub-nap': + + list = [] + for i in range(0,P): + list.append(role(i,inrole)) + list.append(nonce(0,inrole)) + msg = ",".join(list) + + for i in range(1,label+1): + msg = "{ %s }sk(%s), %s" % (msg,role(i,inrole),nonce(i,inrole)) + + msg = "{ %s }pk(%s)" % (msg,role(label+1,inrole)) + + return msg + elif opts.protocol == 'bke-nap': + + list = [] + for i in range(0,P): + list.append(role(i,inrole)) + list.append(nonce(0,inrole)) + msg = ",".join(list) + + for i in range(1,label+1): + msg = "{ %s }sk(%s), %s" % (msg,role(i,inrole),nonce(i,inrole)) + + msg = "{ %s }pk(%s)" % (msg,role(label+1,inrole)) + + return msg + else: + print "Hmm, I don't know how to create the first message for protocol %s" % (opts.protocol) + +def message2 (label,inrole): + global P,variant,opts + + if opts.protocol == "nsl": + noncelist = [] + for i in range (((label + 1) % P),P): + noncelist.append(nonce(i,inrole)) + + return ",".join(weavel(noncelist,[], + (variant & 16 != 0), + False, + False, + False + )) + elif opts.protocol == "bke": + noncelist = [] + for i in range (((label + 1) % P) + 1,P): + noncelist.append(nonce(i,inrole)) + if len(noncelist) == 0: + noncelist.append(zeroconst()) + + return ",".join(weavel(noncelist,[], + (variant & 16 != 0), + False, + False, + False + )) + elif opts.protocol in ['nsl-priv-noprop','nsl-pub-nap']: + msg = message1(P-1,inrole) + for i in range(0,label-P+1): + msg = "{ %s }sk(%s)" % (msg,role(i,inrole)) + + if opts.protocol == 'nsl-pub-nap': + msg = "{ %s }pk(%s)" % (msg,role(label+1,inrole)) + + return msg + elif opts.protocol == 'bke-nap': + msg = message1(P-1,inrole) + for i in range(0,label-P+1): + msg = "{ %s }sk(%s)" % (msg,role(i,inrole)) + + msg = "{ %s }%s" % (msg,nonce((label+1) % P,inrole)) + + return msg + else: + print "Hmm, I don't know how to create the final message for protocol %s" % (opts.protocol) + +def message (label,inrole): + global P,opts + + if opts.protocol in ['bke','nsl']: + s = "{ " + if label < P: + s = s + message1 (label,inrole) + else: + s = s + message2 (label,inrole) + + if opts.protocol == "bke" and not (label < P): + s = s + " }" + nonce((label+1) % P, inrole) + else: + s = s + " }pk(%s)" % role(label+1,inrole) + return s + else: + if label < P: + return message1 (label,inrole) + else: + return message2 (label,inrole) + + +def action (event,label,inrole): + s = "\t\t%s_%i(%s,%s, " % (event,label, role(label,inrole), + role(label+1,inrole)) + s += message (label,inrole) + s += " );\n" + return s + +def recv (label,inrole): + return action ("recv", label,inrole) + + +def send (label,inrole): + return action ("send", label,inrole) + +def roledef (r): + global P,opts + + s = "" + s += "\trole " + role(r,r) + "\n\t{\n" + + # constants for this role + + s += "\t\tconst " + nonce (r,r) + ": Nonce;\n" + + # variables + + s += "\t\tvar " + nr = 0 + for i in range (0,P): + if r != i: + if nr > 0: + s += "," + s += nonce(i,r) + nr += 1 + + s += ": Nonce;\n" + + # implicit role variables + + rolevars = [] + for i in range (0,P): + if variablerole(i,r): + rolevars.append(role(i,r)) + + if rolevars != []: + s += "\t\t// Implicit role variables: " + s += ",".join(rolevars) + s += ": Role;\n" + + # actions + + s += "\n" + if r > 0: + # Initial recv + s += recv(r-1,r) + s += send(r,r) + s += recv(P+r-1,r) + if r < (P-1): + # Final send + s += send(P+r,r) + + # claims + + if opts.protocol in ['bke','nsl','nsl-pub-nap','bke-nap']: + s += "\t\tclaim_%sa( %s, Secret, %s );\n" % (role(r,r), role(r,r), + nonce(r,r)) + s += "\t\tclaim_%sb( %s, Nisynch );\n" % (role(r,r), role(r,r)) + + # close + s += "\t}\n\n" + return s + + +def protocol (args): + global P,variant,opts + + P = int(args[0]) + variant = int(args[1]) + + s = "" + s += "// Generalized %s protocol for %i parties\n\n" % (opts.protocol,P) + s += "// " + str(opts) + "\n\n" + s += "// Variant %i\n" % variant + + if opts.protocol == "bke": + s += "usertype Globalconstant;\n" + s += "const %s: Globalconstant;\n" % (zeroconst()) + + s += "\n" + + s += "protocol mnsl%iv%i(" % (P,variant) + for i in range (0,P): + if i > 0: + s += "," + s += role(i,i) + s += ")\n{\n" + + for i in range (0,P): + s += roledef(i) + + s += "}\n\n" + + s += "\n" + return s + +def main(): + global opts + + (opts,args) = parseArgs() + print protocol(args) + +# Only if main stuff +if __name__ == '__main__': + main() diff --git a/Vagrant Files/files/scyther/Protocols/multi-NSL/test-heuristics.py b/Vagrant Files/files/scyther/Protocols/multi-NSL/test-heuristics.py new file mode 100644 index 0000000..34c03fc --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/multi-NSL/test-heuristics.py @@ -0,0 +1,69 @@ +#!/usr/bin/python +# +# +# Idea: +# +# We test all options for the heuristics [0..31] to compare, +# and sincerely hope on gives a complete proof. +# we slowly refine the tests. +# +import commands + +def startset(): + mainlist = [11, 15] + print "Starting with", mainlist + return mainlist + +def tuplingchoice(heur,variant,P,runs,latupling): + # variant is in range [0..64>, + # where we use the highest bid to signify the + # associativity of the tupling. + + extraflags = "" + if latupling: + extraflags += " --la-tupling" + + # Choose heuristics + extraflags += " --goal-select=%i" % (heur) + + # Time limit + extraflags += " --timer=20" + + s = "./multinsl-generator.py" + s += " %i %i" % (P,variant) + s += " | scyther -a -r%i -m2 --summary %s" % (runs, extraflags) + + ## Old stuff + #s += " | scyther -a -r%i --summary" % runs + + # Show what we're doing + print s + + #s += " | grep \"complete\"" + out = commands.getoutput(s) + if out == "": + #print "Okay" + return False + else: + print out + return True + +def testvariant(h,v,p,r): + if tuplingchoice (h,v,p,r, False): + return True + else: + return tuplingchoice (h,v,p,r, True) + +def scan(testlist, P, runs): + print "Testing using P %i and %i runs." % (P,runs) + for i in testlist: + print "Testing protocol %i." % (i) + for h in range (0,32): + print "Heuristic %i:" % (h) + testvariant (h,i,P,runs) + +def main(): + candidates = startset() + scan(candidates,3,5) + +main() diff --git a/Vagrant Files/files/scyther/Protocols/multi-NSL/test-variants.py b/Vagrant Files/files/scyther/Protocols/multi-NSL/test-variants.py new file mode 100644 index 0000000..ae00ce7 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/multi-NSL/test-variants.py @@ -0,0 +1,79 @@ +#!/usr/bin/python +# +# +# Idea: +# +# We test all variants [0..31] until we are sure they work. Thus, +# we slowly refine the tests. +# +import commands + +def startset(): + return range(0,32) + + mainlist = [11, 15] + print "Starting with", mainlist + return mainlist + +def tuplingchoice(variant,P,runs,latupling): + # variant is in range [0..64>, + # where we use the highest bid to signify the + # associativity of the tupling. + + extraflags = "" + if latupling: + extraflags += " --la-tupling" + + s = "./multinsl-generator.py" + s += " %i %s" % (P,variant) + s += " | scyther -r%i --untyped %s" % (runs, extraflags) + #s += " | scyther -a -r%i --summary" % runs + #print s + s += " | grep \"Fail\"" + out = commands.getoutput(s) + if out == "": + #print "Okay" + return True + else: + #print out + # Thus, MultiNSL P variant has the first attack for n runs + return False + +def testvariant(v,p,r): + if not tuplingchoice (v,p,r, False): + return False + else: + return tuplingchoice (v,p,r, True) + +def removeattacks (testlist, P, runs): + okaylist = [] + for v in testlist: + if testvariant (v, P, runs): + okaylist.append(v) + return okaylist + +def scan(testlist, P, runs): + print "Testing using P %i and %i runs." % (P,runs) + results = removeattacks (testlist, P, runs) + if len(results) < len(testlist): + attacked = [] + for i in range(0,len(testlist)): + if testlist[i] not in results: + attacked.append(testlist[i]) + print "Using P %i and %i runs, we find attacks on %s" % (P,runs, str(attacked)) + print "Therefore, we are left with %i candidates: " % (len(results)), results + + return results + +def main(): + candidates = startset() + for P in range(3,7): + for rundiff in range(0,5): + candidates = scan(candidates,P,P+rundiff) + + print + print "Good variants:" + print candidates + + +main() diff --git a/Vagrant Files/files/scyther/Protocols/needham-schroeder-lowe.spdl b/Vagrant Files/files/scyther/Protocols/needham-schroeder-lowe.spdl new file mode 100644 index 0000000..fabb522 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/needham-schroeder-lowe.spdl @@ -0,0 +1,53 @@ +# Lowe's fixed version of Needham Schroeder Public Key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/nspkLowe.html +# +# +# Note: +# The modelling in SPORE includes a server to distribute the public keys +# of the agents, this is not necessary and it allows for attacks against +# synchronisation and agreement, because the keys that the server sends +# out can be replayed. + +protocol needhamschroederpk-Lowe(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + + send_1(I,S, (I,R)); + recv_2(S,I, {pk(R), R}sk(S)); + send_3(I,R,{Ni,I}pk(R)); + recv_6(R,I, {Ni,Nr,R}pk(I)); + send_7(I,R, {Nr}pk(R)); + claim_I1(I,Secret,Ni); + claim_I2(I,Secret,Nr); + claim_I3(I,Nisynch); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + + recv_3(I,R,{Ni,I}pk(R)); + send_4(R,S,(R,I)); + recv_5(S,R,{pk(I),I}sk(S)); + send_6(R,I,{Ni,Nr,R}pk(I)); + recv_7(I,R,{Nr}pk(R)); + claim_R1(R,Secret,Nr); + claim_R2(R,Secret,Ni); + claim_R3(R,Nisynch); + } + + role S + { + recv_1(I,S,(I,R)); + send_2(S,I,{pk(R),R}sk(S)); + recv_4(R,S,(R,I)); + send_5(S,R,{pk(I),I}sk(S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/needham-schroeder-sk-amend.spdl b/Vagrant Files/files/scyther/Protocols/needham-schroeder-sk-amend.spdl new file mode 100644 index 0000000..189093d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/needham-schroeder-sk-amend.spdl @@ -0,0 +1,66 @@ +# Amended Needham Schroeder Symmetric Key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/nssk_amended.html +# +# +# Note: +# According to SPORE there are no attacks on this protocol, scyther +# finds one however. This has to be investigated further. + + + +# Model dec that is invertible by inc +const dec,inc: Function; +inversekeys(dec,inc); +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol needhamschroedersk-amend(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var Kir: SessionKey; + var T,T2: Ticket; + + send_1(I,R,I); + recv_2(R,I,T); + send_3(I,S,(I,R,Ni,T)); + recv_4(S,I, {Ni,R,Kir,T2}k(I,S)); + send_5(I,R,T2); + recv_6(R,I,{Nr}Kir); + send_7(I,R,{{Nr}dec}Kir); + + claim_I2(I,Secret,Kir); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh Nr: Nonce; + var Kir: SessionKey; + + recv_1(I,R,I); + send_2(R,I,{I,Nr}k(R,S)); + recv_5(I,R,{Kir,Nr,I}k(R,S)); + send_6(R,I,{Nr}Kir); + recv_7(I,R,{{Nr}dec}Kir); + claim_R1(R,Secret,Nr); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni,Nr: Nonce; + fresh Kir: SessionKey; + recv_3(I,S,(I,R,Ni,{I,Nr}k(R,S))); + send_4(S,I,{Ni,R,Kir,{Kir,Nr,I}k(R,S)}k(I,S)); + } + +} + diff --git a/Vagrant Files/files/scyther/Protocols/needham-schroeder-sk.spdl b/Vagrant Files/files/scyther/Protocols/needham-schroeder-sk.spdl new file mode 100644 index 0000000..71a7e6c --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/needham-schroeder-sk.spdl @@ -0,0 +1,56 @@ +# Needham Schroeder Symmetric Key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/nssk.html +# +# + + +# Model dec that is invertible by inc +const dec,inc: Function; +inversekeys(dec,inc); +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol needhamschroedersk(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var Kir: SessionKey; + var T: Ticket; + + send_1(I,S,(I,R,Ni)); + recv_2(S,I, {Ni,R,Kir,T}k(I,S)); + send_3(I,R,T); + recv_4(R,I,{Nr}Kir); + send_5(I,R,{{Nr}dec}Kir); + claim_I2(I,Secret,Kir); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh Nr: Nonce; + var Kir: SessionKey; + + recv_3(I,R,{Kir,I}k(R,S)); + send_4(R,I,{Nr}Kir); + recv_5(I,R,{{Nr}dec}Kir); + claim_R1(R,Secret,Kir); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni: Nonce; + fresh Kir: SessionKey; + recv_1(I,S,(I,R,Ni)); + send_2(S,I,{Ni,R,Kir,{Kir,I}k(R,S)}k(I,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/needham-schroeder.spdl b/Vagrant Files/files/scyther/Protocols/needham-schroeder.spdl new file mode 100644 index 0000000..ea14854 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/needham-schroeder.spdl @@ -0,0 +1,53 @@ +# Needham Schroeder Public Key +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/nspk.html +# +# +# Note: +# The modelling in SPORE includes a server to distribute the public keys +# of the agents, this is not necessary and it allows for attacks against +# synchronisation and agreement, because the keys that the server sends +# out can be replayed. + +protocol needhamschroederpk(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + + send_1(I,S,(I,R)); + recv_2(S,I, {pk(R), R}sk(S)); + send_3(I,R,{Ni,I}pk(R)); + recv_6(R,I, {Ni, Nr}pk(I)); + send_7(I,R, {Nr}pk(R)); + claim_I1(I,Secret,Ni); + claim_I2(I,Secret,Nr); + claim_I3(I,Nisynch); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + + recv_3(I,R,{Ni,I}pk(R)); + send_4(R,S,(R,I)); + recv_5(S,R,{pk(I),I}sk(S)); + send_6(R,I,{Ni,Nr}pk(I)); + recv_7(I,R,{Nr}pk(R)); + claim_R1(R,Secret,Nr); + claim_R2(R,Secret,Ni); + claim_R3(R,Nisynch); + } + + role S + { + recv_1(I,S,(I,R)); + send_2(S,I,{pk(R),R}sk(S)); + recv_4(R,S,(R,I)); + send_5(S,R,{pk(I),I}sk(S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/neumannstub-guttman-hwang.spdl b/Vagrant Files/files/scyther/Protocols/neumannstub-guttman-hwang.spdl new file mode 100644 index 0000000..bcb48d2 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/neumannstub-guttman-hwang.spdl @@ -0,0 +1,105 @@ +# Neumann Stubblebine +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/neumannStubblebine.html +# +# Note: +# In SPORE this protocol is not described correctly, there are in fact 2 +# different protocols (the key establishment protocol and the repeated +# authentication protocol) + +usertype Server, SessionKey, TimeStamp, TicketKey; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + +protocol neustub-GuttmanHwang^Repeat(I,R,S) +{ + fresh Kir: SessionKey; + + role I + { + fresh Mi: Nonce; + var Mr: Nonce; + fresh Kir: SessionKey; + fresh Tr: TimeStamp; + + send_5(I,R,Mi,{I,Kir,Tr}k(R,S)); + recv_6(R,I,{Mi,Mr}Kir); + send_7(I,R,{I,Mr}Kir); + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh Mr: Nonce; + var Tr: TimeStamp; + var Kir: SessionKey; + var Mi: Nonce; + + recv_5(I,R,Mi,{I,Kir,Tr}k(R,S)); + send_6(R,I,{Mi,Mr}Kir); + recv_7(I,R,{I,Mr}Kir); + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + } +} +protocol neustub-GuttmanHwang(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Tb: TimeStamp; + var Kir: SessionKey; + + send_1(I,R, I, Ni); + recv_!3(S,I, { R,Ni,Kir,Tb}k(I,S), T, Nr); + send_!4(I,R,T,{Nr}Kir); + + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + var Ni,Mi: Nonce; + fresh Nr,Mr: Nonce; + var Kir: SessionKey; + fresh Tb: TimeStamp; + var T: Ticket; + + recv_1(I,R, I, Ni); + send_!2(R,S, R, {I, Ni, Tb ,Nr}k(R,S)); + recv_!4(I,R,{I,Kir,Tb}k(R,S),{Nr}Kir); + + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni, Nr: Nonce; + fresh Kir: SessionKey; + var Tb: TimeStamp; + + recv_!2(R,S, R, {I,Ni,Tb,Nr}k(R,S)); + send_!3(S,I, { R, Ni, Kir, Tb}k(I,S), { I,Kir,Tb}k(R,S),Nr ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/neumannstub-guttman.spdl b/Vagrant Files/files/scyther/Protocols/neumannstub-guttman.spdl new file mode 100644 index 0000000..09e7f6e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/neumannstub-guttman.spdl @@ -0,0 +1,105 @@ +# Neumann Stubblebine +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/neumannStubblebine.html +# +# Note: +# In SPORE this protocol is not described correctly, there are in fact 2 +# different protocols (the key establishment protocol and the repeated +# authentication protocol) + +usertype Server, SessionKey, TimeStamp, TicketKey; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + +protocol neustub^Repeat(I,R,S) +{ + fresh Kir: SessionKey; + + role I + { + fresh Mi: Nonce; + var Mr: Nonce; + fresh Kir: SessionKey; + fresh Tr: TimeStamp; + + send_5(I,R,Mi,{I,Kir,Tr}k(R,S)); + recv_6(R,I,{Mi,Mr}Kir); + send_7(I,R,{I,Mr}Kir); + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh Mr: Nonce; + var Tr: TimeStamp; + var Kir: SessionKey; + var Mi: Nonce; + + recv_5(I,R,Mi,{I,Kir,Tr}k(R,S)); + send_6(R,I,{Mi,Mr}Kir); + recv_7(I,R,{I,Mr}Kir); + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + } +} +protocol neustub(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Tb: TimeStamp; + var Kir: SessionKey; + + send_1(I,R, I, Ni); + recv_!3(S,I, { R,Ni,Kir,Tb}k(I,S), T, Nr); + send_4(I,R,T,{Nr}Kir); + + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + var Ni,Mi: Nonce; + fresh Nr,Mr: Nonce; + var Kir: SessionKey; + fresh Tb: TimeStamp; + var T: Ticket; + + recv_1(I,R, I, Ni); + send_!2(R,S, R, {I, Ni, Tb}k(R,S),Nr); + recv_4(I,R,{I,Kir,Tb}k(R,S),{Nr}Kir); + + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni, Nr: Nonce; + fresh Kir: SessionKey; + var Tb: TimeStamp; + + recv_!2(R,S, R, {I,Ni,Tb}k(R,S), Nr); + send_!3(S,I, { R, Ni, Kir, Tb}k(I,S), { I,Kir,Tb}k(R,S),Nr ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/neumannstub-hwang.spdl b/Vagrant Files/files/scyther/Protocols/neumannstub-hwang.spdl new file mode 100644 index 0000000..1546b40 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/neumannstub-hwang.spdl @@ -0,0 +1,71 @@ +# Hwang modified Neumann Stubblebine +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/neumannStubblebineHwang.html +# +# Note: +# According to SPORE there are no attacks on this protocol, scyther +# finds one however. This has to be investigated further. + + +usertype Server, SessionKey, TimeStamp, TicketKey; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + +protocol neustub-Hwang(I,R,S) +{ + role I + { + fresh Ni,Mi: Nonce; + var Nr,Mr: Nonce; + var T: Ticket; + var Tb: TimeStamp; + var Kir: SessionKey; + + send_1(I,R, I, Ni); + recv_!3(S,I, { R,Ni,Kir,Tb}k(I,S), T, Nr); + send_4(I,R,T,{Nr}Kir); + send_5(I,R,Mi,T); + recv_6(R,I,Mr,{Mi}Kir); + send_7(I,R,{Mr}Kir); + + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + var Ni,Mi: Nonce; + fresh Nr,Mr: Nonce; + var Kir: SessionKey; + fresh Tb: TimeStamp; + var T: Ticket; + + recv_1(I,R, I, Ni); + send_!2(R,S, R, {I, Ni, Tb, Nr}k(R,S)); + recv_4(I,R,{I,Kir,Tb}k(R,S),{Nr}Kir); + recv_5(I,R,Mi,T); + send_6(R,I,Mr,{Mi}Kir); + recv_7(I,R,{Mr}Kir); + + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni, Nr: Nonce; + fresh Kir: SessionKey; + var Tb: TimeStamp; + + recv_!2(R,S, R, {I,Ni,Tb,Nr}k(R,S)); + send_!3(S,I, { R, Ni, Kir, Tb}k(I,S), { I,Kir,Tb}k(R,S),Nr ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/neumannstub-keycompromise.spdl b/Vagrant Files/files/scyther/Protocols/neumannstub-keycompromise.spdl new file mode 100644 index 0000000..d803150 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/neumannstub-keycompromise.spdl @@ -0,0 +1,105 @@ +# Neumann Stubblebine +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/neumannStubblebine.html +# +# Note: +# In SPORE this protocol is not described correctly, there are in fact 2 +# different protocols (the key establishment protocol and the repeated +# authentication protocol) + +usertype Server, SessionKey, TimeStamp, TicketKey; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + +protocol neustub^Repeat(I,R,S) +{ + fresh Kir: SessionKey; + + role I + { + fresh Mi: Nonce; + var Mr: Nonce; + fresh Kir: SessionKey; + fresh Tr: TimeStamp; + + send_5(I,R,Mi,{I,Kir,Tr}k(R,S)); + recv_6(R,I,Mr,{Mi}Kir); + send_7(I,R,{Mr}Kir); + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh Mr: Nonce; + var Tr: TimeStamp; + var Kir: SessionKey; + var Mi: Nonce; + + recv_5(I,R,Mi,{I,Kir,Tr}k(R,S)); + send_6(R,I,Mr,{Mi}Kir); + recv_7(I,R,{Mr}Kir); + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + } +} +protocol neustub(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Tb: TimeStamp; + var Kir: SessionKey; + + send_1(I,R, I, Ni); + recv_3(S,I, { R,Ni,Kir,Tb}k(I,S), T, Nr); + send_4(I,R,T,{Nr}Kir); + + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + claim_I4(I,Empty,(Fresh,Kir)); + } + + role R + { + var Ni,Mi: Nonce; + fresh Nr,Mr: Nonce; + var Kir: SessionKey; + fresh Tb: TimeStamp; + var T: Ticket; + + recv_1(I,R, I, Ni); + send_2(R,S, R, {I, Ni, Tb}k(R,S),Nr); + recv_4(I,R,{I,Kir,Tb}k(R,S),{Nr}Kir); + + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + claim_R4(R,Empty,(Fresh,Kir)); + } + + role S + { + var Ni, Nr: Nonce; + fresh Kir: SessionKey; + var Tb: TimeStamp; + + recv_2(R,S, R, {I,Ni,Tb}k(R,S), Nr); + send_3(S,I, { R, Ni, Kir, Tb}k(I,S), { I,Kir,Tb}k(R,S),Nr ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/neumannstub.spdl b/Vagrant Files/files/scyther/Protocols/neumannstub.spdl new file mode 100644 index 0000000..d1d0ee1 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/neumannstub.spdl @@ -0,0 +1,98 @@ +# Neumann Stubblebine +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/neumannStubblebine.html +# +# Note: +# In SPORE this protocol is not described correctly, there are in fact 2 +# different protocols (the key establishment protocol and the repeated +# authentication protocol) + +usertype Server, SessionKey, TimeStamp, TicketKey; +usertype ExpiredTimeStamp; + +protocol neustub^Repeat(I,R,S) +{ + fresh Kir: SessionKey; + + role I + { + fresh Mi: Nonce; + var Mr: Nonce; + fresh Kir: SessionKey; + fresh Tr: TimeStamp; + + send_5(I,R,Mi,{I,Kir,Tr}k(R,S)); + recv_6(R,I,Mr,{Mi}Kir); + send_7(I,R,{Mr}Kir); + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + } + + role R + { + fresh Mr: Nonce; + var Tr: TimeStamp; + var Kir: SessionKey; + var Mi: Nonce; + + recv_5(I,R,Mi,{I,Kir,Tr}k(R,S)); + send_6(R,I,Mr,{Mi}Kir); + recv_7(I,R,{Mr}Kir); + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + } + + role S + { + } +} +protocol neustub(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Tb: TimeStamp; + var Kir: SessionKey; + + send_1(I,R, I, Ni); + recv_!3(S,I, { R,Ni,Kir,Tb}k(I,S), T, Nr); + send_4(I,R,T,{Nr}Kir); + + claim_I1(I,Secret, Kir); + claim_I2(I,Niagree); + claim_I3(I,Nisynch); + } + + role R + { + var Ni,Mi: Nonce; + fresh Nr,Mr: Nonce; + var Kir: SessionKey; + fresh Tb: TimeStamp; + var T: Ticket; + + recv_1(I,R, I, Ni); + send_!2(R,S, R, {I, Ni, Tb}k(R,S),Nr); + recv_4(I,R,{I,Kir,Tb}k(R,S),{Nr}Kir); + + claim_R1(R,Secret, Kir); + claim_R2(R,Niagree); + claim_R3(R,Nisynch); + } + + role S + { + var Ni, Nr: Nonce; + fresh Kir: SessionKey; + var Tb: TimeStamp; + + recv_!2(R,S, R, {I,Ni,Tb}k(R,S), Nr); + send_!3(S,I, { R, Ni, Kir, Tb}k(I,S), { I,Kir,Tb}k(R,S),Nr ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/otwayrees.spdl b/Vagrant Files/files/scyther/Protocols/otwayrees.spdl new file mode 100644 index 0000000..bed12ad --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/otwayrees.spdl @@ -0,0 +1,56 @@ +# Otway Rees +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/otwayRees.html +# + + +const Fresh: Function; +const Compromised: Function; + +usertype String,SessionKey; + +protocol otwayrees(I,R,S) +{ + role I + { + fresh Ni : Nonce; + fresh M : String; + var Kir : SessionKey; + + send_1(I,R, M,I,R,{Ni,M,I,R}k(I,S) ); + recv_4(R,I, M,{Ni,Kir}k(I,S) ); + + claim_I1(I, Secret,Kir); + claim_I2(I, Nisynch); + claim_I3(I, Empty, (Fresh,Kir)); + } + + role R + { + var M : String; + fresh Nr : Nonce; + var Kir : SessionKey; + var T1,T2: Ticket; + + recv_1(I,R, M,I,R, T1 ); + send_2(R,S, M,I,R, T1, { Nr,M,I,R }k(R,S) ); + recv_3(S,R, M, T2, { Nr,Kir }k(R,S) ); + send_4(R,I, M, T2 ); + + claim_R1(R, Secret,Kir); + claim_R2(R, Nisynch); + claim_R3(R, Empty, (Fresh,Kir)); + } + + role S + { + var Ni,Nr : Nonce; + var M : String; + fresh Kir : SessionKey; + + recv_2(R,S, M,I,R, { Ni,M,I,R}k(I,S), { Nr,M,I,R }k(R,S) ); + send_3(S,R, M, { Ni,Kir }k(I,S) , { Nr,Kir }k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/smartright.spdl b/Vagrant Files/files/scyther/Protocols/smartright.spdl new file mode 100644 index 0000000..e3a9719 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/smartright.spdl @@ -0,0 +1,46 @@ +# SmartRight view-only +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/smartright_viewonly.html +# +# Note: +# According to SPORE there are no known attacks on this protocol +# +# Note: +# Scyther finds an attack because the value of VoR in te last message can +# be replaced with an arbitrary value + +hashfunction hash; +usertype SessionKey; +usertype XorKey; +const Vor: XorKey; + +protocol smartright(I,R) +{ + role I + { + fresh VoKey: SessionKey; + fresh VoR: XorKey; + fresh CW; + var VoRi: Nonce; + + send_1(I,R, {VoKey,{CW}VoR}k(I,R)); + recv_2(R,I, VoRi); + send_3(I,R, VoR, {{VoRi}hash}VoKey); + } + + role R + { + var T: Ticket; + var VoR: XorKey; + var VoKey: SessionKey; + fresh VoRi: Nonce; + + recv_1(I,R, {VoKey,T}k(I,R)); + send_2(R,I, VoRi); + recv_3(I,R, VoR,{{VoRi}hash}VoKey); + + claim_R1(R,Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/splice-as-cj.spdl b/Vagrant Files/files/scyther/Protocols/splice-as-cj.spdl new file mode 100644 index 0000000..b393294 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/splice-as-cj.spdl @@ -0,0 +1,66 @@ +# Clark and Jacob modified Hwang and Chen modified SPLICE/AS +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/spliceas3.html +# +# Note: +# The assumptions made here do not comply with those in SPORE +# SPORE assumes that the agents do not know the pk function, but only +# their own public key values. +# This can currently not be modelled. + + +usertype TimeStamp, LifeTime; + +const inc,dec: Function; +inversekeys (inc,dec); + +protocol spliceAS-CJ(I,R,S) +{ + role I + { + fresh N1,N2: Nonce; + fresh T: TimeStamp; + fresh L: LifeTime; + + send_1(I,S, I, R, N1 ); + recv_2(S,I, S, {S, I, N1, R, pk(R)}sk(S) ); + send_3(I,R, I, R, {T, L, {I, N2}pk(R)}sk(I) ); + recv_6(R,I, R, I, {{N2}inc}pk(I) ); + + claim_7(I, Secret, N2); + claim_9(I, Niagree); + claim_10(I, Nisynch); + } + + role S + { + var N1,N3: Nonce; + + recv_1(I,S, I, R, N1 ); + send_2(S,I, S, {S, I, N1, R, pk(R)}sk(S) ); + recv_4(R,S, R, I, N3 ); + send_5(S,R, S, {S, R, N3, pk(I)}sk(S) ); + } + + role R + { + fresh N3: Nonce; + var N2: Nonce; + var T: TimeStamp; + var L: LifeTime; + + var ni: Nonce; + fresh nr: Nonce; + + recv_3(I,R, I, R, {T, L, {I, N2}pk(R)}sk(I) ); + send_4(R,S, R, I, N3 ); + recv_5(S,R, S, {S, R, N3, pk(I)}sk(S) ); + send_6(R,I, R, I, {{N2}inc}pk(I) ); + + claim_8(R, Secret, N2); + claim_11(R, Niagree); + claim_12(R, Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/splice-as-hc.spdl b/Vagrant Files/files/scyther/Protocols/splice-as-hc.spdl new file mode 100644 index 0000000..2f975ad --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/splice-as-hc.spdl @@ -0,0 +1,61 @@ +# Hwang and Chen Modified SPLICE/AS +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/spliceas2.html +# + + +usertype TimeStamp, LifeTime; + +const inc,dec: Function; +inversekeys (inc,dec); + +protocol spliceAS-HC(I,R,S) +{ + role I + { + fresh N1,N2: Nonce; + fresh T: TimeStamp; + fresh L: LifeTime; + + send_1(I,S, I, R, N1 ); + recv_2(S,I, S, {S, I, N1, R, pk(R)}sk(S) ); + send_3(I,R, I, R, {I, T, L, {N2}pk(R)}sk(I) ); + recv_6(R,I, R, I, {R, {N2}inc}pk(I) ); + + claim_7(I, Secret, N2); + claim_9(I, Niagree); + claim_10(I, Nisynch); + } + + role S + { + var N1,N3: Nonce; + + recv_1(I,S, I, R, N1 ); + send_2(S,I, S, {S, I, N1, R, pk(R)}sk(S) ); + recv_4(R,S, R, I, N3 ); + send_5(S,R, S, {S, R, N3, I, pk(I)}sk(S) ); + } + + role R + { + fresh N3: Nonce; + var N2: Nonce; + var T: TimeStamp; + var L: LifeTime; + + var ni: Nonce; + fresh nr: Nonce; + + recv_3(I,R, I, R, {I, T, L, {N2}pk(R)}sk(I) ); + send_4(R,S, R, I, N3 ); + recv_5(S,R, S, {S, R, N3, I, pk(I)}sk(S) ); + send_6(R,I, R, I, {R, {N2}inc}pk(I) ); + + claim_8(R, Secret, N2); + claim_11(R, Niagree); + claim_12(R, Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/splice-as.spdl b/Vagrant Files/files/scyther/Protocols/splice-as.spdl new file mode 100644 index 0000000..b1d8e18 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/splice-as.spdl @@ -0,0 +1,66 @@ +# SPLICE/AS +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/spliceas.html +# +# Note: +# The assumptions made here do not comply with those in SPORE +# SPORE assumes that the agents do not know the pk function, but only +# their own public key values. +# This can currently not be modelled. + + +usertype TimeStamp, LifeTime; + +const inc,dec: Function; +inversekeys (inc,dec); + +protocol spliceAS(I,R,S) +{ + role I + { + fresh N1,N2: Nonce; + fresh T: TimeStamp; + fresh L: LifeTime; + + send_1(I,S, I, R, N1 ); + recv_2(S,I, S, {S, I, N1, pk(R)}sk(S) ); + send_3(I,R, I, R, {I, T, L, {N2}pk(R)}sk(I) ); + recv_6(R,I, R, I, {R, {N2}inc}pk(I) ); + + claim_7(I, Secret, N2); + claim_9(I, Niagree); + claim_10(I, Nisynch); + } + + role S + { + var N1,N3: Nonce; + + recv_1(I,S, I, R, N1 ); + send_2(S,I, S, {S, I, N1, pk(R)}sk(S) ); + recv_4(R,S, R, I, N3 ); + send_5(S,R, S, {S, R, N3, pk(I)}sk(S) ); + } + + role R + { + fresh N3: Nonce; + var N2: Nonce; + var T: TimeStamp; + var L: LifeTime; + + var ni: Nonce; + fresh nr: Nonce; + + recv_3(I,R, I, R, {I, T, L, {N2}pk(R)}sk(I) ); + send_4(R,S, R, I, N3 ); + recv_5(S,R, S, {S, R, N3, pk(I)}sk(S) ); + send_6(R,I, R, I, {R, {N2}inc}pk(I) ); + + claim_8(R, Secret, N2); + claim_11(R, Niagree); + claim_12(R, Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/tmn.spdl b/Vagrant Files/files/scyther/Protocols/tmn.spdl new file mode 100644 index 0000000..c6fb55f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/tmn.spdl @@ -0,0 +1,51 @@ +# TMN +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/tmn.html +# +# Note: +# According to Boyd and Mathuria Kb is the session key this is not clear +# from the description in SPORE +usertype SessionKey; + +const Fresh: Function; +const Compromised: Function; + +protocol tmn(I,R,S) +{ + role I + { + fresh Ki: SessionKey; + var Kr: SessionKey; + + send_1(I,S, R,{Ki}pk(S) ); + recv_4(S,I, R,{Kr}Ki ); + + claim_I1(I,Secret,Kr); + claim_I2(I,Nisynch); + claim_I3(I,Empty,(Fresh,Kr)); + } + + role R + { + fresh Kr: SessionKey; + + recv_2(S,R, I ); + send_3(R,S, I, { Kr }pk(S) ); + + claim_R1(R,Secret,Kr); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,Kr)); + } + + role S + { + var Ki,Kr: SessionKey; + + recv_1(I,S, R,{Ki}pk(S) ); + send_2(S,R, I ); + recv_3(R,S, I, { Kr }pk(S) ); + send_4(S,I, R,{Kr}Ki ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/wmf-lowe.spdl b/Vagrant Files/files/scyther/Protocols/wmf-lowe.spdl new file mode 100644 index 0000000..86b34e3 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/wmf-lowe.spdl @@ -0,0 +1,63 @@ +# Lowe modified Wide Mouthed Frog +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wideMouthedFrogLowe.html +# +# Note: +# According to SPORE there are no known attacks on this protocol, scyther +# finds one however this has to do with the unusual assumption that every +# agent can recognise and will reject to messages that it has created +# itself. + +usertype SessionKey; +usertype TimeStamp; +usertype ExpiredTimeStamp; +const succ,pred: Function; +inversekeys (succ,pred); +const Fresh: Function; +const Compromised: Function; + +protocol wmf-Lowe(I,R,S) +{ + role I + { + fresh Kir: SessionKey; + fresh Ti: TimeStamp; + var Kr: SessionKey; + var Nr: Nonce; + + send_1(I,S, I, {Ti, R, Kir}k(I,S)); + recv_3(R,I,{Nr}Kir); + send_4(I,R,{{Nr}succ}Kir); + + claim_I1(I,Secret,Kir); + claim_I2(I,Nisynch); + claim_I3(I,Empty,(Fresh,Kir)); + } + + role R + { + var Ts: TimeStamp; + var Kir: SessionKey; + fresh Nr: Nonce; + + recv_2(S,R, {Ts, I, Kir}k(R,S) ); + send_3(R,I, {Nr}Kir); + recv_4(I,R, {{Nr}succ}Kir); + + claim_R1(R,Secret,Kir); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,Kir)); + } + + role S + { + var Kir: SessionKey; + fresh Ts: TimeStamp; + var Ti: TimeStamp; + + recv_1(I,S, I,{Ti, R, Kir}k(I,S) ); + send_2(S,R, {Ts, I, Kir}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/wmf.spdl b/Vagrant Files/files/scyther/Protocols/wmf.spdl new file mode 100644 index 0000000..758843a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/wmf.spdl @@ -0,0 +1,54 @@ +# Wide Mouthed Frog +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wideMouthedFrog.html +# +# Note +# The name of the party that has generated a message was added in order +# to model the property described in SPORE that an agent can identify +# its own messages and will reject them. + +usertype SessionKey; +usertype TimeStamp; +usertype ExpiredTimeStamp; + +const Fresh: Function; +const Compromised: Function; + +protocol wmf(I,R,S) +{ + role I + { + fresh Kir: SessionKey; + fresh Ti: TimeStamp; + var Kr: SessionKey; + + send_1(I,S, I, {I, Ti, R, Kir}k(I,S)); + + claim_I1(I,Secret,Kir); + claim_I2(I,Empty,(Fresh,Kir)); + } + + role R + { + var Ts: TimeStamp; + var Kir: SessionKey; + + recv_2(S,R, {S, Ts, I, Kir}k(R,S) ); + + claim_R1(R,Secret,Kir); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,Kir)); + } + + role S + { + var Kir: SessionKey; + fresh Ts: TimeStamp; + var Ti: TimeStamp; + + recv_1(I,S, I,{I, Ti, R, Kir}k(I,S) ); + send_2(S,R, {S, Ts, I, Kir}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/woo-lam-pi-1.spdl b/Vagrant Files/files/scyther/Protocols/woo-lam-pi-1.spdl new file mode 100644 index 0000000..7e4e09d --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/woo-lam-pi-1.spdl @@ -0,0 +1,41 @@ +# Woo and Lam Pi 1 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPi1.html +# + +protocol woolamPi-1(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {I,R,Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I,R, T}k(R,S)); + recv_5(S,R, {I,R, Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I,R, {I,R,Nr}k(I,S)}k(R,S)); + send_5(S,R, {I,R,Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/woo-lam-pi-2.spdl b/Vagrant Files/files/scyther/Protocols/woo-lam-pi-2.spdl new file mode 100644 index 0000000..5d767d6 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/woo-lam-pi-2.spdl @@ -0,0 +1,41 @@ +# Woo and Lam Pi 2 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPi2.html +# + +protocol woolamPi-2(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {I,Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I, T}k(R,S)); + recv_5(S,R, {I, Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I, {I,Nr}k(I,S)}k(R,S)); + send_5(S,R, {I,Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/woo-lam-pi-3.spdl b/Vagrant Files/files/scyther/Protocols/woo-lam-pi-3.spdl new file mode 100644 index 0000000..1db544e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/woo-lam-pi-3.spdl @@ -0,0 +1,41 @@ +# Woo and Lam Pi 2 +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPi3.html +# + +protocol woolamPi-3(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I, T}k(R,S)); + recv_5(S,R, {I, Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I, {Nr}k(I,S)}k(R,S)); + send_5(S,R, {I,Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/woo-lam-pi-f.spdl b/Vagrant Files/files/scyther/Protocols/woo-lam-pi-f.spdl new file mode 100644 index 0000000..22f028c --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/woo-lam-pi-f.spdl @@ -0,0 +1,41 @@ +# Woo and Lam Pi f +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPif.html +# + +protocol woolamPi-f(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {I,R,Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I, R, Nr, T}k(R,S)); + recv_5(S,R, {I, R, Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I, R, Nr,{I,R,Nr}k(I,S)}k(R,S)); + send_5(S,R, {I, R, Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/woo-lam-pi.spdl b/Vagrant Files/files/scyther/Protocols/woo-lam-pi.spdl new file mode 100644 index 0000000..0c01c27 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/woo-lam-pi.spdl @@ -0,0 +1,45 @@ +# Woo and Lam Pi +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamPi.html +# +# Note: +# Scyther finds an attack that appears to be legit, but is not present in +# SPORE. +# + +protocol woolamPi(I,R,S) +{ + role I + { + var Nr: Nonce; + + send_1(I,R, I); + recv_2(R,I, Nr); + send_3(I,R, {Nr}k(I,S)); + + } + + role R + { + fresh Nr: Nonce; + var T: Ticket; + + recv_1(I,R, I); + send_2(R,I, Nr); + recv_3(I,R, T); + send_4(R,S, {I, T}k(R,S)); + recv_5(S,R, {Nr}k(R,S)); + + claim_R1(R,Nisynch); + } + + role S + { + var Nr: Nonce; + + recv_4(R,S, {I,{Nr}k(I,S)}k(R,S)); + send_5(S,R, {Nr}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/woo-lam.spdl b/Vagrant Files/files/scyther/Protocols/woo-lam.spdl new file mode 100644 index 0000000..7e28057 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/woo-lam.spdl @@ -0,0 +1,64 @@ +# Woo and Lam Mutual Authentication +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/wooLamMutual.html +# + + +usertype SessionKey; + +const Fresh: Function; +const Compromised: Function; + +protocol woolam(I,R,S) +{ + role I + { + fresh N1: Nonce; + var Kir: SessionKey; + var N2: Nonce; + + send_1(I,R, I, N1); + recv_2(R,I, R, N2); + send_3(I,R, {I, R, N1, N2}k(I,S)); + recv_6(R,I, {R, N1, N2, Kir}k(I,S), {N1,N2}Kir); + send_7(I,R, {N2}Kir); + + + claim_I1(I,Secret,Kir); + claim_I2(I,Nisynch); + claim_I3(I,Empty,(Fresh,Kir)); + } + + role R + { + fresh N2: Nonce; + var N1: Nonce; + var Kir: SessionKey; + var T1,T2: Ticket; + + recv_1(I,R, I, N1); + send_2(R,I, R, N2); + recv_3(I,R, T1); + send_4(R,S, T1, {I, R, N1, N2}k(R,S)); + recv_5(S,R, T2, {I, N1, N2, Kir}k(R,S)); + send_6(R,I, T2, {N1,N2}Kir); + recv_7(I,R, {N2}Kir); + + claim_R1(R,Secret,Kir); + claim_R2(R,Nisynch); + claim_R3(R,Empty,(Fresh,Kir)); + } + + role S + { + fresh Kir: SessionKey; + var N1,N2: Nonce; + + recv_4(R,S, {I, R, N1, N2}k(I,S), {I, R, N1, N2}k(R,S)); + send_5(S,R, {R, N1, N2, Kir}k(I,S), {I, N1, N2, Kir}k(R,S)); + } +} + + + diff --git a/Vagrant Files/files/scyther/Protocols/yahalom-ban.spdl b/Vagrant Files/files/scyther/Protocols/yahalom-ban.spdl new file mode 100644 index 0000000..b865362 --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/yahalom-ban.spdl @@ -0,0 +1,54 @@ +# BAN simplified version of Yahalom +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/yahalomBAN.html +# + +usertype SessionKey; +const Fresh: Function; +const Compromised: Function; + +protocol yahalom-BAN(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Kir: SessionKey; + + send_1(I,R, I,Ni); + recv_3(S,I, Nr, {R,Kir,Ni}k(I,S), T ); + send_4(I,R, T, {Nr}Kir ); + + claim_I1(I, Secret,Kir); + claim_I2(I, Nisynch); + claim_I3(I, Empty, (Fresh,Kir)); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + var T: Ticket; + var Kir: SessionKey; + + recv_1(I,R, I,Ni); + send_2(R,S, R, Nr, {I,Ni}k(R,S) ); + recv_4(I,R, {I,Kir,Nr}k(R,S) , {Nr}Kir ); + + claim_R1(R, Secret,Kir); + claim_R2(R, Nisynch); + claim_R3(R, Empty, (Fresh,Kir)); + } + + role S + { + fresh Kir: SessionKey; + var Ni,Nr: Nonce; + + recv_2(R,S, R, Nr, {I,Ni}k(R,S) ); + send_3(S,I, Nr, {R,Kir,Ni}k(I,S), {I,Kir,Nr}k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/yahalom-lowe.spdl b/Vagrant Files/files/scyther/Protocols/yahalom-lowe.spdl new file mode 100644 index 0000000..308a62a --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/yahalom-lowe.spdl @@ -0,0 +1,52 @@ +# Lowe's modified version of Yahalom +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/yahalomLowe.html +# +# + +usertype SessionKey; + + +protocol yahalom-Lowe(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var Kir: SessionKey; + + send_1(I,R, I,Ni); + recv_3(S,I, {R,Kir,Ni,Nr}k(I,S) ); + send_5(I,R, {I, R, S, Nr}Kir ); + + claim_I1(I, Secret,Kir); + claim_I2(I, Nisynch); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + var Kir: SessionKey; + + recv_1(I,R, I,Ni); + send_2(R,S, {I,Ni,Nr}k(R,S) ); + recv_4(S,R, {I,Kir}k(R,S)); + recv_5(I,R, {I, R, S, Nr}Kir); + + claim_R1(R, Secret,Kir); + claim_R2(R, Nisynch); + } + + role S + { + fresh Kir: SessionKey; + var Ni,Nr: Nonce; + + recv_2(R,S, {I,Ni,Nr}k(R,S) ); + send_3(S,I, {R,Kir,Ni,Nr}k(I,S)); + send_4(S,R, {I,Kir}k(R,S)); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/yahalom-paulson.spdl b/Vagrant Files/files/scyther/Protocols/yahalom-paulson.spdl new file mode 100644 index 0000000..a8dfe1e --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/yahalom-paulson.spdl @@ -0,0 +1,56 @@ +# Paulson's strengthened version of Yahalom +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/yahalomPaulson.html +# +# + +const Fresh: Function; +const Compromised: Function; + +usertype SessionKey; + +protocol yahalom-Paulson(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Kir: SessionKey; + + send_1(I,R, I,Ni); + recv_3(S,I, Nr, {R,Kir,Ni}k(I,S), T ); + send_4(I,R, T, {Nr}Kir ); + + claim_I1(I, Secret,Kir); + claim_I2(I, Nisynch); + claim_I3(I, Empty, (Fresh,Kir)); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + var T: Ticket; + var Kir: SessionKey; + + recv_1(I,R, I,Ni); + send_2(R,S, R, Nr, {I,Ni}k(R,S) ); + recv_4(I,R, {I,R, Kir, Nr}k(R,S) , {Nr}Kir ); + + claim_R1(R, Secret,Kir); + claim_R2(R, Nisynch); + claim_R3(R, Empty, (Fresh,Kir)); + } + + role S + { + fresh Kir: SessionKey; + var Ni,Nr: Nonce; + + recv_2(R,S, R, Nr, {I,Ni}k(R,S) ); + send_3(S,I, Nr, {R,Kir,Ni}k(I,S), {I,R,Kir,Nr}k(R,S) ); + } +} + diff --git a/Vagrant Files/files/scyther/Protocols/yahalom.spdl b/Vagrant Files/files/scyther/Protocols/yahalom.spdl new file mode 100644 index 0000000..063817f --- /dev/null +++ b/Vagrant Files/files/scyther/Protocols/yahalom.spdl @@ -0,0 +1,52 @@ +# Yahalom +# +# Modelled after the description in the SPORE library +# http://www.lsv.ens-cachan.fr/spore/yahalom.html +# +# + +usertype SessionKey; + +protocol yahalom(I,R,S) +{ + role I + { + fresh Ni: Nonce; + var Nr: Nonce; + var T: Ticket; + var Kir: SessionKey; + + send_1(I,R, I,Ni); + recv_3(S,I, {R,Kir,Ni,Nr}k(I,S), T ); + send_4(I,R, T, {Nr}Kir ); + + claim_I1(I, Secret,Kir); + } + + role R + { + fresh Nr: Nonce; + var Ni: Nonce; + var T: Ticket; + var Kir: SessionKey; + + recv_1(I,R, I,Ni); + send_2(R,S, R, {I,Ni,Nr}k(R,S) ); + recv_4(I,R, {I,Kir}k(R,S) , {Nr}Kir ); + + claim_R1(R, Secret,Kir); + } + + role S + { + fresh Kir: SessionKey; + var Ni,Nr: Nonce; + + recv_2(R,S, R, {I,Ni,Nr}k(R,S) ); + send_3(S,I, {R,Kir,Ni,Nr}k(I,S), {I,Kir}k(R,S) ); + + claim(S, Secret, Ni); + claim(S, Secret, Nr); + } +} + diff --git a/Vagrant Files/files/scyther/README.md b/Vagrant Files/files/scyther/README.md new file mode 100644 index 0000000..706df8d --- /dev/null +++ b/Vagrant Files/files/scyther/README.md @@ -0,0 +1,66 @@ +The Scyther tool +================ + +Scyther is a tool for the symbolic analysis of security protocols. It is +developed by Cas Cremers, and is available from +<http://www.cs.ox.ac.uk/people/cas.cremers/scyther/index.html>. + +The below instructions apply only to the *distribution version* of +the Scyther tool. If you are working from the source files, some paths may be +slightly different, and it is recommended to follow the instructions in [../README.md](../README.md). + +Running the scyther tool +------------------------ + +### Graphical user interface ### + +The graphical user interface can be started by running `scyther-gui.py`, +e.g., enter the following in a terminal and press return + + python ./scyther-gui.py + +### Command-line usage ### + +In the directory `./Scyther` there should be an executable for the +Scyther backend. Its name depends on the platform: + + * `scyther-linux` (Linux) + * `scyther-w32` (Windows) + * `scyther-mac` (Mac OS X) + +If this executable does not exist, you probably downloaded the source +files, and will need to compile it first. See `../README.md` for further +details. + +There are also various test scripts (for usage in Linux) in this +directory. + +Obtaining the sources +---------------------- + +Scyther is being developed on *Github*, and its complete source files are +availabe from +<https://github.com/cascremers/scyther>. + +Manual +------ + +We are currently rewriting the manual. The current (incomplete) +distribution version of the manual can be found here: + + * [./scyther-manual.pdf](scyther-manual.pdf) + + +Protocol Models +--------------- + +The protocol models have the extension `.spdl` and can be found in the following directories: + + * [./Protocols](Protocols) and its subdirectories. + +License +------- + +Currently the Scyther tool is licensed under the GPL 2, as indicated in +the source code. Contact Cas Cremers if you have any questions. + diff --git a/Vagrant Files/files/scyther/Scripts/regression-test.py b/Vagrant Files/files/scyther/Scripts/regression-test.py new file mode 100644 index 0000000..beabc74 --- /dev/null +++ b/Vagrant Files/files/scyther/Scripts/regression-test.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +def testSet(blacklist=[]): + import os + + prefix = "../Protocols/" + dl = os.listdir(prefix) + fl = [] + for fn in dl: + if fn.endswith(".spdl"): + okay = True + for fb in blacklist: + if fn.startswith(fb): + okay = False + break + if okay: + fl.append((prefix,fn)) + return fl + +def evaluate(fn,prefix=""): + import subprocess + import tempfile + + cmd = "../Scyther/scyther-linux" + args = [cmd,"--max-runs=4","--plain",fn] + + fstdout = tempfile.TemporaryFile() + fstderr = tempfile.TemporaryFile() + + subprocess.call(args,stdout=fstdout,stderr=fstderr) + + fstdout.seek(0) + fstderr.seek(0) + + res = "" + for l in fstdout.xreadlines(): + res += prefix + l.strip() + "\n" + #for l in fstderr.xreadlines(): + # print l + + fstdout.close() + fstderr.close() + return res + + +def main(): + dest = "regression-test.txt" + output = "regression-test.txt.tmp" + + fp = open(output, 'w') + + fl = testSet(blacklist=['ksl']) + cnt = 1 + tres = "" + for (prefix,fn) in sorted(fl): + print "Evaluating %s (%i/%i)" % (fn,cnt,len(fl)) + res = evaluate(prefix+fn, "%s\t" % (fn)) + fp.write(res) + tres += res + cnt += 1 + fp.close() + + fp = open(dest, 'w') + fp.write(tres) + fp.close() + + print res + + + +if __name__ == '__main__': + main() diff --git a/Vagrant Files/files/scyther/Scripts/regression-test.txt b/Vagrant Files/files/scyther/Scripts/regression-test.txt new file mode 100644 index 0000000..3fa247f --- /dev/null +++ b/Vagrant Files/files/scyther/Scripts/regression-test.txt @@ -0,0 +1,64 @@ +BKE.spdl claim bke,I SKR_4 kir Ok [no attack within bounds] +BKE.spdl claim bke,R SKR_7 kir Ok [no attack within bounds] +TLS-Paulson.spdl claim tlspaulson,a SKR_9a hash(sid,hash(pms,na,nb),na,pa,a,nb,pb,b,true) Ok [no attack within bounds] +TLS-Paulson.spdl claim tlspaulson,a SKR_9b hash(sid,hash(pms,na,nb),na,pa,a,nb,pb,b,false) Ok [no attack within bounds] +TLS-Paulson.spdl claim tlspaulson,b SKR_10a hash(sid,hash(pms,na,nb),na,pa,a,nb,pb,b,true) Ok [no attack within bounds] +TLS-Paulson.spdl claim tlspaulson,b SKR_10b hash(sid,hash(pms,na,nb),na,pa,a,nb,pb,b,false) Ok [no attack within bounds] +ccitt509-1.spdl claim ccitt509-1,R Nisynch_3 - Ok [proof of correctness] +ccitt509-1c.spdl claim ccitt509-1c,R Nisynch_3 - Ok [proof of correctness] +ccitt509-3.spdl claim ccitt509-3,I Nisynch_I1 - Ok [proof of correctness] +ccitt509-3.spdl claim ccitt509-3,I Secret_I2 Ya Ok [proof of correctness] +ccitt509-3.spdl claim ccitt509-3,I Secret_I3 Yb Ok [proof of correctness] +ccitt509-3.spdl claim ccitt509-3,R Nisynch_R1 - Fail [at least 3 attacks] +ccitt509-3.spdl claim ccitt509-3,R Secret_R2 Ya Ok [no attack within bounds] +ccitt509-3.spdl claim ccitt509-3,R Secret_R3 Yb Ok [no attack within bounds] +ccitt509-ban3.spdl claim ccitt509-ban3,I Nisynch_4 - Ok [proof of correctness] +ccitt509-ban3.spdl claim ccitt509-ban3,R Nisynch_5 - Ok [no attack within bounds] +needham-schroeder-lowe.spdl claim needhamschroederpk-Lowe,I Secret_I1 Ni Ok [no attack within bounds] +needham-schroeder-lowe.spdl claim needhamschroederpk-Lowe,I Secret_I2 Nr Ok [no attack within bounds] +needham-schroeder-lowe.spdl claim needhamschroederpk-Lowe,I Nisynch_I3 - Fail [at least 3 attacks] +needham-schroeder-lowe.spdl claim needhamschroederpk-Lowe,R Secret_R1 Nr Ok [no attack within bounds] +needham-schroeder-lowe.spdl claim needhamschroederpk-Lowe,R Secret_R2 Ni Ok [no attack within bounds] +needham-schroeder-lowe.spdl claim needhamschroederpk-Lowe,R Nisynch_R3 - Fail [at least 3 attacks] +needham-schroeder.spdl claim needhamschroederpk,I Secret_I1 Ni Ok [no attack within bounds] +needham-schroeder.spdl claim needhamschroederpk,I Secret_I2 Nr Ok [no attack within bounds] +needham-schroeder.spdl claim needhamschroederpk,I Nisynch_I3 - Fail [at least 3 attacks] +needham-schroeder.spdl claim needhamschroederpk,R Secret_R1 Nr Fail [at least 5 attacks] +needham-schroeder.spdl claim needhamschroederpk,R Secret_R2 Ni Fail [at least 5 attacks] +needham-schroeder.spdl claim needhamschroederpk,R Nisynch_R3 - Fail [at least 3 attacks] +smartright.spdl claim smartright,R Nisynch_R1 - Fail [at least 1 attack] +splice-as-cj.spdl claim spliceAS-CJ,I Secret_7 N2 Ok [no attack within bounds] +splice-as-cj.spdl claim spliceAS-CJ,I Niagree_9 - Fail [at least 1 attack] +splice-as-cj.spdl claim spliceAS-CJ,I Nisynch_10 - Fail [at least 1 attack] +splice-as-cj.spdl claim spliceAS-CJ,R Secret_8 N2 Ok [no attack within bounds] +splice-as-cj.spdl claim spliceAS-CJ,R Niagree_11 - Fail [at least 1 attack] +splice-as-cj.spdl claim spliceAS-CJ,R Nisynch_12 - Fail [at least 1 attack] +splice-as-hc.spdl claim spliceAS-HC,I Secret_7 N2 Ok [no attack within bounds] +splice-as-hc.spdl claim spliceAS-HC,I Niagree_9 - Fail [at least 1 attack] +splice-as-hc.spdl claim spliceAS-HC,I Nisynch_10 - Fail [at least 1 attack] +splice-as-hc.spdl claim spliceAS-HC,R Secret_8 N2 Ok [no attack within bounds] +splice-as-hc.spdl claim spliceAS-HC,R Niagree_11 - Fail [at least 1 attack] +splice-as-hc.spdl claim spliceAS-HC,R Nisynch_12 - Fail [at least 1 attack] +splice-as.spdl claim spliceAS,I Secret_7 N2 Ok [no attack within bounds] +splice-as.spdl claim spliceAS,I Niagree_9 - Fail [at least 1 attack] +splice-as.spdl claim spliceAS,I Nisynch_10 - Fail [at least 1 attack] +splice-as.spdl claim spliceAS,R Secret_8 N2 Ok [no attack within bounds] +splice-as.spdl claim spliceAS,R Niagree_11 - Fail [at least 1 attack] +splice-as.spdl claim spliceAS,R Nisynch_12 - Fail [at least 1 attack] +woo-lam-pi-1.spdl claim woolamPi-1,R Nisynch_R1 - Fail [at least 2 attacks] +woo-lam-pi-2.spdl claim woolamPi-2,R Nisynch_R1 - Fail [at least 3 attacks] +woo-lam-pi-3.spdl claim woolamPi-3,R Nisynch_R1 - Fail [at least 2 attacks] +woo-lam-pi-f.spdl claim woolamPi-f,R Nisynch_R1 - Fail [at least 1 attack] +woo-lam-pi.spdl claim woolamPi,R Nisynch_R1 - Fail [at least 2 attacks] +yahalom-ban-paulson-modified.spdl claim yahalom-BAN-Paulson-modified,A Secret_5 kab Ok [no attack within bounds] +yahalom-ban-paulson-modified.spdl claim yahalom-BAN-Paulson-modified,B Secret_6 kab Ok [no attack within bounds] +yahalom-ban-paulson.spdl claim yahalom-BAN-Paulson,A SKR_5 kab Ok [no attack within bounds] +yahalom-ban-paulson.spdl claim yahalom-BAN-Paulson,B SKR_6 kab Ok [no attack within bounds] +yahalom-lowe.spdl claim yahalom-Lowe,I Secret_I1 Kir Ok [proof of correctness] +yahalom-lowe.spdl claim yahalom-Lowe,I Nisynch_I2 - Ok [proof of correctness] +yahalom-lowe.spdl claim yahalom-Lowe,R Secret_R1 Kir Ok [proof of correctness] +yahalom-lowe.spdl claim yahalom-Lowe,R Nisynch_R2 - Ok [no attack within bounds] +yahalom.spdl claim yahalom,I Secret_I1 Kir Ok [no attack within bounds] +yahalom.spdl claim yahalom,R Secret_R1 Kir Ok [no attack within bounds] +yahalom.spdl claim yahalom,S Secret_S1 Ni Fail [at least 1 attack] +yahalom.spdl claim yahalom,S Secret_S2 Nr Ok [no attack within bounds] diff --git a/Vagrant Files/files/scyther/Scripts/scytherview.py b/Vagrant Files/files/scyther/Scripts/scytherview.py new file mode 100644 index 0000000..9973867 --- /dev/null +++ b/Vagrant Files/files/scyther/Scripts/scytherview.py @@ -0,0 +1,113 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Convert scyther dot output to a printable PDF and display it +# +# This is a simple hack to be able to quickly use the graphical output +# of Scyther if one only has graphviz, but not elementtree and wxPython. +# +# Note 1: only works under Linux currently, because of silly assumptions +# on temporary directories and pdf viewers. +# +# Note 2: this code assumes that both scyther-linux and dot can be found in the +# environment (i.e. PATH variable) +# +import os,sys,commands +import os.path + +tempcount = 0 + +def generateTemp(extension='tmp'): + # We need a temporary file to hold the generated postscript stuff before + # it is converted to pdf + global tempcount + + tempcount = tempcount + 1 + tmp = '/tmp/output_dot_%s_%i.%s' % (os.getpid(),tempcount,extension) + + try: + os.unlink(tmp) + except: + pass + return tmp + +def scyther_to_dotfile(): + """ Run Scyther, return dotfile name """ + + mydir = os.path.dirname(__file__) + scythername = os.path.join(mydir, "../Scyther/scyther-linux") + + args = " ".join(sys.argv[1:]) + tmpdotfile = generateTemp('dot') + + command = "%s --plain --dot-output %s > %s" % (scythername, args, tmpdotfile) + output = commands.getoutput(command) + return (output,tmpdotfile) + +def dotfile_to_pdffile(dotfile,outfile=None): + """ Generate a PDF file (name is returned) from an input dotfile + name """ + + tmp = generateTemp('ps') + + # First split the input per digraph and call dot with -Gsize arguments to make + # it fit to a landscape page + dotdata = open(dotfile, "r") + f = None + for line in dotdata.xreadlines(): + if (line.find('digraph') == 0): + f = os.popen("dot -Gsize='11.0,8.0' -Gratio=fill -Tps >>%s" % (tmp),'w') + print >>f, line + dotdata.close() + + if not f: + return None + f.close() + + if not outfile: + outfile = generateTemp('pdf') + + # Now convert the resulting stuff to a pdf + os.system('ps2pdf -sPAPERSIZE=a4 -g7014x5300 -r600 %s %s' % (tmp,outfile)) + #os.system('ps2pdf -g8300x6250 -r600 %s %s' % (tmp,outf)) + + # And remove the temp file + os.unlink(tmp) + + return outfile + +def main(): + (output,dotfile) = scyther_to_dotfile() + print output + pdffile = dotfile_to_pdffile(dotfile) + os.unlink(dotfile) + if pdffile: + commands.getoutput("kpdf %s" % pdffile) + os.unlink(pdffile) + else: + print "No graphs generated." + +if __name__ == '__main__': + if len(sys.argv) > 1: + main() + else: + print "Please provide the name of an input file." + diff --git a/Vagrant Files/files/scyther/Scyther/.gitignore b/Vagrant Files/files/scyther/Scyther/.gitignore new file mode 100644 index 0000000..c7e14a4 --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/.gitignore @@ -0,0 +1,3 @@ +scyther-mac +scyther-linux +scyther-w32.exe diff --git a/Vagrant Files/files/scyther/Scyther/Attack.py b/Vagrant Files/files/scyther/Scyther/Attack.py new file mode 100644 index 0000000..d07ee6e --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/Attack.py @@ -0,0 +1,71 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Attack +# + +import Trace +import Term +#import Classification +from Misc import * + +class Attack(object): + def __init__(self): + self.broken = [] + self.match = None + self.initialKnowledge = [] + self.inverseKeys = [] + self.protocol = None + self.semiTrace = Trace.SemiTrace() + self.variables = [] + self.protocoldescr = {} + self.id = None + self.knowledge = None + self.untrusted = [] + self.typeflaws = False + self.commandline = '' + self.scytherDot = None + self.claim = None # refers to parent claim + + def getInvolvedAgents(self): + result = [] + for run in self.semiTrace.runs: + for agent in run.roleAgents.values(): + result.append(agent) + return uniq(result) + + def buildKnowledge(self): + if not self.knowledge: + self.knowledge = Term.Knowledge(self) + self.knowledge.buildKnowledge() + + def getPrecedingLabelSet(self,event): + return self.protocoldescr[str(event.label[0])].getPrecedingLabelSet(event.label) + + def getPrecedingRoleSet(self,event): + return self.protocoldescr[str(event.label[0])].getPrecedingRoleSet(event.label) + + #def classify(self): + # classification = Classification.Classification(self) + # classification.classifyClaims() + # classification.classifyInitiations() + # classification.classifyComplexity() + # classification.classifyTypeflaws() + # return classification diff --git a/Vagrant Files/files/scyther/Scyther/Claim.py b/Vagrant Files/files/scyther/Scyther/Claim.py new file mode 100644 index 0000000..c048789 --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/Claim.py @@ -0,0 +1,197 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Claim +# + +import Term + +def stateDescription(okay,n=1,caps=False): + if okay: + s = "trace pattern" + if n != 1: + s += "s" + else: + s = "attack" + if n != 1: + s += "s" + if caps: + s = s[0].upper() + s[1:] + return s + + +class Claim(object): + def __init__(self): + self.id = None # a unique id string, consisting of 'protocol,label' + self.claimtype = None + self.label = None + self.shortlabel = None + self.protocol = None + self.role = None + self.parameter = None + self.failed = 0 + self.count = 0 + self.states = 0 + self.complete = False + self.timebound = False + self.attacks = [] + self.state = False # if true, it is a state, not an attack + self.okay = None # true if good, false if bad + + # derived info + self.foundstates = False + self.foundproof = False + + def analyze(self): + + # determine short label + # We need the rightmost thingy here + label = self.label + while isinstance(label,Term.TermTuple): + label = label[1] + self.shortlabel = label + + # determine id + self.id = "%s,%s" % (self.protocol,self.shortlabel) + + # some additional properties + if str(self.claimtype) == 'Reachable': + self.state = True + if self.failed > 0: + self.foundstates = True + if self.complete: + self.foundproof = True + + # status + # normally, with attacks, okay means none + self.okay = (self.failed == 0) + if self.state: + # but the logic reverses when it is states and not + # attacks... + self.okay = (not self.okay) + + def stateName(self,count=1,caps=False): + return stateDescription(self.state,count,caps) + + def getRank(self): + """ + Return claim rank + 0 - really failed + 1 - probably failed + 2 - probably okay + 3 - really okay + """ + n = len(self.attacks) + if not self.okay: + # not okay + if (self.state and self.complete) or ((not self.state) and (n > 0)): + return 0 + else: + return 1 + else: + # okay! + if not ((self.state and (n > 0)) or ((not self.state) and self.complete)): + return 2 + else: + return 3 + + def getVerified(self): + """ + returns an element of [None,'Verified','Falsified'] + """ + opts = ['Falsified',None,None,'Verified'] + return opts[self.getRank()] + + + def getColour(self): + """ + Returns a colour that expresses the state + """ + colours = ['#FF0000', + '#800000', + '#005800', + '#00B000'] + return colours[self.getRank()] + + def getOkay(self): + """ + Returns a very brief statement about the claim. + + Originally the two mid options had a question mark appended, but + from a users' point of view this might only be more confusing, + so I took them out again. + """ + colours = ['Fail', + 'Fail', + 'Ok', + 'Ok'] + return colours[self.getRank()] + + def getComment(self): + """ + returns a sentence describing the results for this claim + """ + n = len(self.attacks) + atxt = self.stateName(n) + remark = "" + if not self.complete: + if n == 0: + # no attacks, no states within bounds + remark = "No %s within bounds" % (atxt) + else: + # some attacks/states within bounds + remark = "At least %i %s" % (n,atxt) + else: + if n == 0: + # no attacks, no states + remark = "No %s" % (atxt) + else: + # there exist n states/attacks (within any number of runs) + remark = "Exactly %i %s" % (n,atxt) + return remark + "." + + def triplet(self): + """ + Return protocol,role,label triplet + """ + return (self.protocol, self.role, self.shortlabel) + + def describe(self): + s = str(self.claimtype) + if self.parameter: + s+= "(%s)" % self.parameter + + return s + + def roledescribe(self): + return "%s: %s" % (self.role,self.describe()) + + def __str__(self): + """ + Resulting string + """ + s = "claim id [%s], %s" % (self.id,self.describe()) + + # determine status + s+= "\t: %s" % self.getComment() + + return s + + diff --git a/Vagrant Files/files/scyther/Scyther/Error.py b/Vagrant Files/files/scyther/Scyther/Error.py new file mode 100644 index 0000000..88f5db8 --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/Error.py @@ -0,0 +1,121 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Scyther interface error classes +# + +#--------------------------------------------------------------------------- + +class Error(Exception): + """Base class for exceptions in this module.""" + pass + +class ScytherError(Error): + """Exception raised for errors generated by the backend + + Attributes: + errorlist -- list of error lines are retrieved from the + backend + """ + + def __init__(self, errorlist,filenames=None,options=None): + self.errorlist = errorlist + self.filenames = filenames + self.options = options + + def __str__(self): + s = "Scyther backend reported errors" + if len(self.filenames) == 0: + s = s + " for unknown files." + if len(self.filenames) == 1: + s = s + " for file %s" % (self.filenames) + if len(self.filenames) > 1: + s = s + " for files %s" % (self.filenames) + s = s + "\n" + s = s + "Options: '%s'\n\n" % (self.options) + S = s + "Error details:\n" + s = s + "\n".join(self.errorlist) + return s + +class InputError(Error): + """Exception raised for errors in the input. + + Attributes: + expression -- input expression in which the error occurred + message -- explanation of the error + """ + + def __init__(self, expression, message): + self.expression = expression + self.message = message + +class BinaryError(Error): + """Raised when the Scyther executable is not found. + + Attributes: + file -- file location at which we should have been able to find it. + """ + + def __init__(self, file): + self.file = file + + def __str__(self): + return "Could not find Scyther executable at '%s'" % (self.file) + + +class NoBinaryError(Error): + """Raised when the Scyther executable is not defined. + + Attributes: + None. + """ + + def __str__(self): + return "Scyther class attribute 'program' was not defined." + + +class UnknownPlatformError(Error): + """Raised when the platform is not supported yet. + + Attributes: + platform -- string describing the platform. + """ + + def __init__(self, platform): + self.platform = platform + + def __str__(self): + return "The %s platform is currently unsupported." % self.platform + +class StringListError(Error): + """Raised when the a string should be a list of strings or a string + + Attributes: + obj -- object that did not fit + """ + + def __init__(self, obj): + self.obj = obj + + def __str__(self): + return "Got '%s', which is type '%s' instead of a (list of) string." % (self.obj, type(self.obj)) + +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Scyther/FindDot.py b/Vagrant Files/files/scyther/Scyther/FindDot.py new file mode 100644 index 0000000..c70c3ff --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/FindDot.py @@ -0,0 +1,129 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# FindDot.py +# +# Since version 2.31, GraphViz no longer sets the PATH environment variable on Windows. +# The sole reason of existence for this file is to solve this issue automatically if possible. + +#--------------------------------------------------------------------------- +""" Import externals """ +import sys +import os +#--------------------------------------------------------------------------- +""" Import internals """ +import Misc +#--------------------------------------------------------------------------- + +DOTLOCATION = None + +#--------------------------------------------------------------------------- + +def testDot(fpath): + + try: + cmd = "%s -V" % (fpath) + (sts,sout,serr) = Misc.safeCommandOutput(cmd) + if sts != -1: + if "version" in sout + serr: + return True + except: + pass + + return False + +#--------------------------------------------------------------------------- + +def scanPrefix(pf,name): + + if pf.endswith("*"): + import glob + + gl = glob.glob(pf) + for pf in gl: + for root,dirs,files in os.walk(pf): + for d in dirs: + npf = os.path.join(root,d) + res = scanPrefix(npf,name) + if res != None: + return res + + return None + + fpath = os.path.join(pf,name) + if len(pf) > 0: + fpath = "\"%s\"" % (fpath) + if testDot(fpath) == True: + return fpath + + return None + + +def scanLocations(): + if sys.platform.startswith("win"): + prefixes = ["", \ + "C:\Program Files\Graphviz*", \ + "C:\Program Files (x86)\Graphviz*" ] + name = "dot.exe" + else: + prefixes = [""] + name = "dot" + + for pf in prefixes: + path = scanPrefix(pf,name) + if path != None: + return path + + return None + +#--------------------------------------------------------------------------- + +def findDot(): + global DOTLOCATION + + # Cache the results + if DOTLOCATION != None: + return DOTLOCATION + + DOTLOCATION = scanLocations() + if DOTLOCATION == None: + Misc.panic(""" +Could not find the required 'dot' program, which is part of the Graphviz suite. +Please install it from http://www.graphviz.org/ + +Ubuntu users: install the 'graphviz' package. + +Windows users: make sure that Graphviz is installed and + that the location of the 'dot' program is in + the PATH environment variable. + +Restarting your system may be needed for Scyther to locate any newly installed +programs. + """) + return DOTLOCATION + +#--------------------------------------------------------------------------- + +if __name__ == '__main__': + Misc.panic(findDot()) + +#--------------------------------------------------------------------------- + +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Scyther/Misc.py b/Vagrant Files/files/scyther/Scyther/Misc.py new file mode 100644 index 0000000..e41abd8 --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/Misc.py @@ -0,0 +1,158 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Misc.py +# Various helper functions + +#--------------------------------------------------------------------------- + +""" Import externals """ +import sys +import os.path +try: + from subprocess import Popen,PIPE +except: + panic(""" +Cannot import 'subprocess.Popen' module. + +You need at least Python 2.4 to use this program. +""") + +#--------------------------------------------------------------------------- + +def confirm(question): + answer = '' + while answer not in ('y','n'): + print question, + answer = raw_input().lower() + return answer == 'y' + +def exists(func,list): + return len(filter(func,list)) > 0 + +def forall(func,list): + return len(filter(func,list)) == len(list) + +def uniq(li): + result = [] + for elem in li: + if (not elem in result): + result.append(elem) + return result + +# Return a sorted copy of a list +def sorted(li): + result = li[:] + result.sort() + return result + + +# ensurePath: wraps os.makedirs +def ensurePath(pt): + """ + Make sure the path exists: if not, create the directories one by one + + By example: + + Call with "dog/cat/bone" ensures that afterwards, this subdirectory structure (dog/cat/bone) exists, with 'bone' a directory. + It ensures this by doing the procedure for "dog", then "dog/cat", etc... + """ + + if not os.path.isdir(pt): + # Note that os.path.exists(pt) may still hold. In this case the next command will cause an error. + os.makedirs(pt) + + +# path +def mypath(file): + """ Construct a file path relative to the scyther-gui main directory + """ + # Determine base directory (taking symbolic links into account) + cmd_file = os.path.realpath(os.path.abspath(inspect.getfile( inspect.currentframe() ))) + basedir = os.path.split(cmd_file)[0] + return os.path.join(basedir,file) + +def getShell(): + """ + Determine if we want a shell for Popen + """ + if sys.platform.startswith("win"): + shell=False + else: + # Needed to handle the string input correctly (as opposed to a sequence where the first element is the executable) + # This is not needed on Windows, where it has a different effect altogether. + # See http://docs.python.org/library/subprocess.html?highlight=subprocess#module-subprocess + shell=True + return shell + +def safeCommandOutput(cmd, storePopen=None): + """ Execute a command and return (sts,sout,serr). + Meant for short outputs, as output is stored in memory and + not written to a file. + """ + p = Popen(cmd, shell=getShell(), stdout=PIPE, stderr=PIPE) + if storePopen != None: + storePopen(p) + (sout,serr) = p.communicate() + + return (p.returncode,sout,serr) + +def safeCommand(cmd, storePopen=None): + """ Execute a command with some arguments. Safe cross-platform + version, I hope. """ + + try: + p = Popen(cmd, shell=getShell()) + if storePopen != None: + storePopen(p) + sts = p.wait() + except KeyboardInterrupt, EnvironmentError: + raise + except: + print "Wile processing [%s] we had an" % (cmd) + print "unexpected error:", sys.exc_info()[0] + print + sts = -1 + raise # For now still raise + + return sts + + +def panic(text): + """ + Errors that occur before we even are sure about wxPython etc. are dumped + on the command line and reported using Tkinter. + """ + + try: + import Tkinter + except: + print text + sys.exit(-1) + + print text + + root = Tkinter.Tk() + w = Tkinter.Label(root, justify=Tkinter.LEFT, padx = 10, text=text) + w.pack() + root.mainloop() + + sys.exit(-1) + diff --git a/Vagrant Files/files/scyther/Scyther/Scyther.py b/Vagrant Files/files/scyther/Scyther/Scyther.py new file mode 100644 index 0000000..0de9bb6 --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/Scyther.py @@ -0,0 +1,648 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Scyther interface +# + +#--------------------------------------------------------------------------- + +""" Import externals """ +import os +import os.path +import sys +import StringIO +import tempfile +try: + import hashlib + HASHLIB = True +except ImportError: + HASHLIB = False + pass + +#--------------------------------------------------------------------------- + +""" Import scyther components """ +import XMLReader +import Error +import Claim +from Misc import * + +#--------------------------------------------------------------------------- + +""" +Globals +""" + +FirstCheck = True + +#--------------------------------------------------------------------------- + +""" +Get current directory (for this file) +""" +def getMyDir(): + return os.path.dirname( os.path.realpath( __file__ ) ) + +""" +The default path for the binaries is the current one. +""" +def getBinDir(): + return getMyDir() + +""" +Return Cache prefix path +Returns None if not existent +""" +def getCacheDir(): + + tmpdir = None + + # Check if user chose the path + cachedirkey = "SCYTHERCACHEDIR" + if cachedirkey in os.environ.keys(): + tmpdir = os.environ[cachedirkey] + if tmpdir == "": + # Special value: if the variable is present, but equals the empty string, we disable caching. + return None + else: + # Otherwise take from path + tmpdir = tempfile.gettempdir() + + # If not none, append special name + if tmpdir != None: + tmpdir = os.path.join(tmpdir,"Scyther-cache") + + return tmpdir + + + +#--------------------------------------------------------------------------- + +def Check(): + """ + Various dynamic checks that can be performed before starting the + backend. + """ + + global FirstCheck + + # First time + if FirstCheck: + """ + Perform any checks that only need to be done the first time. + """ + FirstCheck = False + + # Every time + + # Check Scyther backend program availability + program = getScytherBackend() + CheckSanity(program) + + +#--------------------------------------------------------------------------- + +def CheckSanity(program): + """ + This is where the existence is checked of the Scyther backend. + """ + + if not os.path.isfile(program): + raise Error.BinaryError, program + +#--------------------------------------------------------------------------- + +def EnsureString(x,sep=" "): + """ + Takes a thing that is either a list or a string. + Turns it into a string. If it was a list, <sep> is inserted, and the + process iterats. + + TODO does not accept unicode yet, that is something that must be + handled to or we run into wxPython problems eventually. + """ + if type(x) is str: + return x + + elif type(x) is list: + newlist = [] + for el in x: + newlist.append(EnsureString(el,sep)) + return sep.join(newlist) + + else: + raise Error.StringListError, x + + +#--------------------------------------------------------------------------- + +def getScytherBackend(): + # Where is my executable? + # + # Auto-detect platform and infer executable name from that + # + if "linux" in sys.platform: + + """ linux """ + scythername = "scyther-linux" + + elif "darwin" in sys.platform: + + """ OS X """ + scythername = "scyther-mac" + + elif sys.platform.startswith('win'): + + """ Windows """ + scythername = "scyther-w32.exe" + + else: + + """ Unsupported""" + raise Error.UnknownPlatformError, sys.platform + + program = os.path.join(getBinDir(),scythername) + return program + + +#--------------------------------------------------------------------------- + +class Scyther(object): + def __init__ ( self): + + # Init + self.program = getScytherBackend() + self.spdl = None + self.inputfile = None + self.filenames = [] + self.options = "" + self.claims = None + self.errors = None + self.errorcount = 0 + self.warnings = None + self.run = False + self.output = None + self.cmd = None + + # defaults + self.xml = True # this results in a claim end, otherwise we simply get the output + + def setInput(self,spdl): + self.spdl = spdl + self.inputfile = None + self.guessFileNames() + + def setFile(self,filename): + self.inputfile = filename + self.filenames = [self.inputfile] + self.spdl = "" + fp = open(filename,"r") + for l in fp.readlines(): + self.spdl += l + fp.close() + + def addFile(self,filename): + self.inputfile = None + if not self.spdl: + self.spdl = "" + fp = open(filename,"r") + for l in fp.readlines(): + self.spdl += l + fp.close() + self.guessFileNames() + + def guessFileNames(self,spdl=None): + """ + Try to extract filenames (well, actually, protocol names) sloppily from some spdl script. + + There are two modes: + + [init] : If the spdl parameter is empty or None, we reset the filenames and extract from self.spdl + [add] : If the spdl parameter is non-empty, add the extracted filenames to an existing list + + """ + + if (spdl == None) or (len(spdl) == 0): + spdl = self.spdl + if spdl == None: + spdl = "" + self.filenames = [] + + for sl in spdl.splitlines(): + l = sl.strip() + prefix = "protocol " + postfix = "(" + x = l.find(prefix) + if x >= 0: + # The prefix occurs + y = l.find(postfix,x+len(prefix)) + if y >= 0: + gn = l[x+len(prefix):y] + # check for helper protocols + if not gn.startswith("@"): + if gn not in self.filenames: + self.filenames.append(gn) + + def addArglist(self,arglist): + for arg in arglist: + self.options += " %s" % (arg) + + def doScytherCommand(self, spdl, args, checkKnown=False, storePopen=None): + """ + Cached version of the 'real' below + + TODO: CC: One possible problem with the caching is the side-effect, e.g., scyther writing to specific named output files. These are not + captured in the cache. I don't have a good solution for that yet. + """ + global HASHLIB + + # Can we use the cache? + canCache = False + if HASHLIB: + cacheDir = getCacheDir() + if cacheDir != None: + canCache = True + else: + cacheDir = None + + # If we cannot use the cache, we either need to compute or, if checking for cache presense,... + if not canCache: + if checkKnown == True: + # not using the cache, so we don't have it already + return False + else: + # Need to compute + return self.doScytherCommandReal(spdl,args, storePopen=storePopen) + + # Apparently we are supporsed to be able to use the cache + m = hashlib.sha256() + if spdl == None: + m.update("[spdl:None]") + else: + m.update(spdl) + if args == None: + m.update("[args:None]") + else: + m.update(args) + + uid = m.hexdigest() + + # Split the uid to make 256 subdirectories with 256 subdirectories... + prefixlen = 2 + uid1 = uid[:prefixlen] + uid2 = uid[prefixlen:prefixlen+2] + uid3 = uid[prefixlen+2:] + + # Possibly we could also decide to store input and arguments in the cache to analyze things later + + # Construct: cachePath/uid1/uid2/... + path = os.path.join(cacheDir,uid1,uid2) + name1 = "%s.out" % (uid3) + name2 = "%s.err" % (uid3) + + fname1 = os.path.join(path, name1) + fname2 = os.path.join(path, name2) + + try: + """ + Try to retrieve the result from the cache + """ + fh1 = open(fname1,"r") + out = fh1.read() + fh1.close() + fh2 = open(fname2,"r") + err = fh2.read() + fh2.close() + if checkKnown == True: + # We got to here, so we have it + return True + else: + # Not checking cache, we need the result + return (out,err) + except: + pass + + """ + Something went wrong, do the real thing and cache afterwards + """ + if checkKnown == True: + # We were only checking, abort + return False + + (out,err) = self.doScytherCommandReal(spdl,args, storePopen=storePopen) + + try: + # Try to store result in cache + ensurePath(path) + + fh1 = open(fname1,"w") + fh1.write(out) + fh1.close() + + fh2 = open(fname2,"w") + fh2.write(err) + fh2.close() + except: + pass + + return (out,err) + + + def doScytherCommandReal(self, spdl, args, storePopen=None): + """ + Run Scyther backend on the input + + Arguments: + spdl -- string describing the spdl text + args -- arguments for the command-line + storePopen -- callback function to register Popen objects (used for process kill by other threads) + Returns: + (output,errors) + output -- string which is the real output + errors -- string which captures the errors + """ + + if self.program == None: + raise Error.NoBinaryError + + # Sanitize input somewhat + if spdl == "": + # Scyther hickups on completely empty input + spdl = "\n" + + # Extract filenames for error reporting later + self.guessFileNames(spdl=spdl) + + # Generate temporary files for the output. + # Requires Python 2.3 though. + (fde,fne) = tempfile.mkstemp() # errors + (fdo,fno) = tempfile.mkstemp() # output + if spdl: + (fdi,fni) = tempfile.mkstemp() # input + + # Write (input) file + fhi = os.fdopen(fdi,'w+b') + fhi.write(spdl) + fhi.close() + + # Generate command line for the Scyther process + self.cmd = "" + self.cmd += "\"%s\"" % self.program + self.cmd += " --append-errors=%s" % fne + self.cmd += " --append-output=%s" % fno + self.cmd += " %s" % args + if spdl: + self.cmd += " %s" % fni + + # Only for debugging, really + ##print self.cmd + + # Start the process + safeCommand(self.cmd, storePopen=storePopen) + + # reseek + fhe = os.fdopen(fde) + fho = os.fdopen(fdo) + errors = fhe.read() + output = fho.read() + + # clean up files + fhe.close() + fho.close() + os.remove(fne) + os.remove(fno) + if spdl: + os.remove(fni) + + return (output,errors) + + def sanitize(self): + """ Sanitize some of the input """ + self.options = EnsureString(self.options) + + def verify(self,extraoptions=None,checkKnown=False,storePopen=None): + """ Should return a list of results """ + """ If checkKnown == True, we do not call Scyther, but just check the cache, and return True iff the result is in the cache """ + + # Cleanup first + self.sanitize() + + # prepare arguments + args = "" + if self.xml: + args += " --dot-output --xml-output --plain" + args += " %s" % self.options + if extraoptions: + # extraoptions might need sanitizing + args += " %s" % EnsureString(extraoptions) + + # Are we only checking the cache? + if checkKnown == True: + return self.doScytherCommand(self.spdl, args, checkKnown=checkKnown, storePopen=storePopen) + + # execute + (output,errors) = self.doScytherCommand(self.spdl, args, storePopen=storePopen) + self.run = True + + # process errors + self.errors = [] + self.warnings = [] + for l in errors.splitlines(): + line = l.strip() + if len(line) > 0: + # filter out any non-errors (say maybe only claim etc) and count + # them. + if line.startswith("claim\t"): + # Claims are lost, reconstructed from the XML output + pass + elif line.startswith("warning"): + # Warnings are stored seperately + self.warnings.append(line) + else: + # otherwise it is an error + self.errors.append(line) + + self.errorcount = len(self.errors) + if self.errorcount > 0: + raise Error.ScytherError(self.errors,filenames=self.filenames,options=self.options) + + # process output + self.output = output + self.validxml = False + self.claims = [] + if self.xml: + if len(output) > 0: + if output.startswith("<scyther>"): + + # whoohee, xml + self.validxml = True + + xmlfile = StringIO.StringIO(output) + reader = XMLReader.XMLReader() + self.claims = reader.readXML(xmlfile) + + # Determine what should be the result + if self.xml: + return self.claims + else: + return self.output + + def verifyOne(self,cl=None,checkKnown=False,storePopen=None): + """ + Verify just a single claim with an ID retrieved from the + procedure below, 'scanClaims', or a full claim object + + If checkKnown is True, return if the result is already known (but never recompute). + """ + if cl: + # We accept either a claim or a claim id + if isinstance(cl,Claim.Claim): + cl = cl.id + return self.verify("--filter=%s" % cl, checkKnown=checkKnown,storePopen=storePopen) + else: + # If no claim, then its just normal verification + return self.verify(checkKnown=checkKnown,storePopen=storePopen) + + def scanClaims(self): + """ + Retrieve the list of claims. Of each element (a claim), claim.id + can be passed to --filter=X or 'verifyOne' later. + A result of 'None' means that some errors occurred. + """ + self.verify("--scan-claims") + if self.errorcount > 0: + return None + else: + self.validxml = False # Signal that we should not interpret the output as XML + return self.claims + + def getClaim(self,claimid): + if self.claims: + for cl in self.claims: + if cl.id == claimid: + return cl + return None + + def __str__(self): + if self.run: + if self.errorcount > 0: + return "%i errors:\n%s" % (self.errorcount, "\n".join(self.errors)) + else: + if self.xml and self.validxml: + s = "Verification results:\n" + for cl in self.claims: + s += str(cl) + "\n" + return s + else: + return self.output + else: + return "Scyther has not been run yet." + +#--------------------------------------------------------------------------- + +def GetClaims(filelist, filterlist=None): + """ + Given a list of file names in filelist, + returns a dictionary of filenames to lists claim names. + Filenames which yielded no claims are filtered out. + + Filterlist may be None or a list of claim names (Secret, SKR, Niagree etc). + """ + + dict = {} + for fname in filelist: + try: + sc = Scyther() + sc.setFile(fname) + l = sc.scanClaims() + if l != None: + cl = [] + for claim in l: + if filterlist == None: + cl.append(claim.id) + else: + if claim.claimtype in filterlist: + cl.append(claim.id) + dict[fname] = cl + except: + pass + return dict + +#--------------------------------------------------------------------------- + +def FindProtocols(path="",filterProtocol=None): + """ + Find a list of protocol names + + Note: Unix only! Will not work under windows. + """ + + import commands + + cmd = "find %s -iname '*.spdl'" % (path) + plist = commands.getoutput(cmd).splitlines() + nlist = [] + for prot in plist: + if filterProtocol != None: + if filterProtocol(prot): + nlist.append(prot) + else: + nlist.append(prot) + return nlist + +#--------------------------------------------------------------------------- + +def GetInfo(html=False): + """ + Retrieve a tuple (location,string) with information about the tool, + retrieved from the --expert --version data + """ + + program = getScytherBackend() + arg = "--expert --version" + sc = Scyther() + (output,errors) = sc.doScytherCommand(spdl=None, args=arg) + if not html: + return (program,output) + else: + sep = "<br>\n" + html = "Backend: %s%s" % (program,sep) + for l in output.splitlines(): + l.strip() + html += "%s%s" % (l,sep) + return html + + +def GetLicense(): + """ + Retrieve license information. + """ + + program = getScytherBackend() + arg = "--license" + sc = Scyther() + (output,errors) = sc.doScytherCommand(spdl=None, args=arg) + return output + + +#--------------------------------------------------------------------------- + +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/Scyther/Term.py b/Vagrant Files/files/scyther/Scyther/Term.py new file mode 100644 index 0000000..9369aa2 --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/Term.py @@ -0,0 +1,223 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Term +# +import Trace +from Misc import * + +class InvalidTerm(TypeError): + "Exception used to indicate that a given term is invalid" + + +class Knowledge(object): + def __init__(self,attack): + self.attack = attack + self.knowledge = [] + + def getInverse(self,term): + for pair in self.attack.inverseKeys: + if term == pair[0]: + return pair[1] + if term == pair[1]: + return pair[0] + + # Get the inverse key + def getInverseKey(self,term): + # First try to see if the entire term has an inverse + result = self.getInverse(term) + if result != None: + return result + + # If it is an apply term, try to see if the function has an inverse + if isinstance(term,TermApply): + result = self.getInverse(term.function) + if result != None: + return TermApply(result,term.argument) + + # No inverse found, so term is its own inverse + return term + + # Add a term to the knowledge + def add(self,term): + if term == None: + return + added = False + for x in term.deriveTerms(self): + if not x in self.knowledge: + added = True + self.knowledge.append(x) + + # Something new was added, maybe this can help us to decrypt a term + # that we could not decrypt before + if added: + for x in self.knowledge: + if isinstance(x,TermEncrypt): + self.add(x) + + def canDerive(self,term): + # We can derive free variables, because we can even choose them + if isinstance(term,TermVariable) and term.isFree(): + return True + # We can derive a term if it is in the knowledge + # or all terms required to construct it are in the knowledge + if exists(lambda x: x == term,self.knowledge): + return True + constructors = term.constructorTerms() + + if len(constructors) == 1 and constructors[0] == term: + # This is a single term, there is no need to look at constructor + # terms as we have already looked at the complete term + return False + + return forall(lambda x: self.canDerive(x),constructors) + + + # Knowledge is the initial knowledge and all messages in sends + def buildKnowledge(self): + self.knowledge = self.attack.initialKnowledge[:] + for run in self.attack.semiTrace.runs: + # Intruder actions do not add knowledge processing them + # is a waste of time + if run.intruder: + continue + for event in run: + if isinstance(event,Trace.EventSend): + self.add(event.message) + self.add(event.fr) + self.add(event.to) + +class Term(object): + def __init__(self): + self.types = None + + def __str__(self): + raise InvalidTerm + + def constructorTerms(self): + raise InvalidTerm + + def deriveTerms(self,knowledge): + raise InvalidTerm + + # Two terms are equal when their string rep is equal + def __cmp__(self,other): + return cmp(str(self),str(other)) + + +class TermConstant(Term): + def __init__(self, constant): + Term.__init__(self) + self.value = str(constant) + + def deriveTerms(self,knowledge): + return [self] + + def constructorTerms(self): + return [self] + + def __str__(self): + return self.value + +class TermEncrypt(Term): + def __init__(self, value, key): + Term.__init__(self) + self.value = value + self.key = key + + def deriveTerms(self,knowledge): + # In order to unpack an encrypted term we have to have the inverse key + inverse = knowledge.getInverseKey(self.key) + if knowledge.canDerive(inverse): + return [self] + [self.value] + self.value.deriveTerms(knowledge) + else: + return [self] + + def constructorTerms(self): + return [self.value,self.key] + + def __str__(self): + return "{%s}%s" % (self.value, self.key) + +class TermApply(Term): + def __init__(self, function, argument): + Term.__init__(self) + self.function = function + self.argument = argument + + def constructorTerms(self): + return [self.function,self.argument] + + def deriveTerms(self,knowledge): + return [self] + + def __str__(self): + return "%s(%s)" % (self.function, self.argument) + +class TermVariable(Term): + def __init__(self, name, value): + Term.__init__(self) + self.name = name + self.value = value + + def isFree(self): + return self.value == None + + def constructorTerms(self): + if self.value != None: + return [self.value] + else: + return [self.name] + + def deriveTerms(self,knowledge): + if self.value != None: + return [self,self.value] + self.value.deriveTerms(knowledge) + else: + return [self,self.name] + + def __str__(self): + if (self.value != None): + return str(self.value) + else: + return str(self.name) + +class TermTuple(Term): + def __init__(self, op1, op2): + Term.__init__(self) + self.op1 = op1 + self.op2 = op2 + + def __str__(self): + return "%s,%s" % (self.op1,self.op2) + + def constructorTerms(self): + return [self.op1,self.op2] + + def deriveTerms(self,knowledge): + return [self,self.op1,self.op2]+self.op1.deriveTerms(knowledge)+self.op2.deriveTerms(knowledge) + + def __getitem__(self,index): + if index == 0: + return self.op1 + elif index == 1: + return self.op2 + else: + return self.op2.__getitem__(index-1) + diff --git a/Vagrant Files/files/scyther/Scyther/Trace.py b/Vagrant Files/files/scyther/Scyther/Trace.py new file mode 100644 index 0000000..31e31cc --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/Trace.py @@ -0,0 +1,358 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Trace +# +from Misc import * + +class InvalidAction(TypeError): + "Exception used to indicate that a given action is invalid" + +class InvalidEvent(TypeError): + "Exception used to indicate that a given event is invalid" + +class SemiTrace(object): + def __init__(self): + self.runs = [] + + def totalCount(self): + count = 0 + for run in self.runs: + count += len(run.eventList) + return count + + def sortActions(self,actionlist): + newlist = actionlist[:] + newlist.sort(lambda x,y: self.getOrder(x,y)) + return newlist + + def getEnabled(self,previous): + enabled = [] + for run in self.runs: + for event in run: + if event in previous or event in enabled: + continue + prec = self.getPrecedingEvents(event,previous) + if len(prec) == 0: + enabled.append(event) + return enabled + + # Returns run,index tuples for all connections + def getConnections(self,event,removeIntruder=False): + if not removeIntruder: + return event.follows + result = [] + if event.run.intruder: + for before in event.getBefore(): + result.extend(self.getConnections(before,removeIntruder)) + + for x in event.follows: + fol = self.getEvent(x) + # If this is an intruder action descend into it + if fol.run.intruder: + result.extend(self.getConnections(fol,removeIntruder)) + else: + result.append(x) + return uniq(result) + + # Return the minimum set of preceding events for a given event + # that is the events before this event in the same run and all + # actions required by the partional ordering + # If previous is non empty remove all events already in previous + def getPrecedingEvents(self,event,previous=[]): + # If it is cached return cached version + if event.preceding != None: + return filter(lambda x: x not in previous,event.preceding) + preceding = [] + for prec in event.getBefore(): + preceding.append(prec) + preceding.extend(self.getPrecedingEvents(prec)) + for x in event.follows: + fol = self.getEvent(x) + preceding.append(fol) + preceding.extend(self.getPrecedingEvents(fol)) + preceding = uniq(preceding) + event.preceding = preceding + preceding = filter(lambda x: x not in previous,preceding) + return preceding + + # Returns -1 if the first event has to be before the second one + # +1 if the second event has to be before the first one + # 0 if there is no order defined on the two events + def getOrder(self,event1,event2): + if (event1 in self.getPrecedingEvents(event2)): + return -1 + if (event2 in self.getPrecedingEvents(event1)): + return 1 + return 0 + + # Get event by run id and index + def getEvent(self,idx): + (rid,index) = idx + for run in self.runs: + if run.id != rid: + continue + for event in run: + if event.index == index: + return event + raise InvalidEvent + + # Get all claim events in the trace + def getClaims(self): + claims = [] + for run in self.runs: + for event in run: + if isinstance(event,EventClaim): + claims.append(event) + return claims + + # Returns a list of all initiation events in the semitrace + def getInitiations(self): + initiations = [] + for run in self.runs: + # Initiations are runs of honest agents + if (run.intruder): + continue + # Which contain no recvs before the first send + for action in run: + if (isinstance(action,EventRead)): + break + elif (isinstance(action,EventSend)): + initiations.append(action) + break + return initiations + + # Get all runs performed by a specific agent + def getAgentRuns(self,agent): + result = [] + for run in self.runs: + if run.getAgent() == agent: + result.append(run) + return result + + # Return a list of all runs that are parallel with this run + def getParallelRuns(self,run): + parallel = [] + first = run.getFirstAction() + # Process all events that are before the end of the run + for event in self.getPrecedingEvents(run.getLastAction()): + # Only count those we haven't found yet + if event.run in parallel or event.run == run: + continue + # If the event is also after the beginning of the run it is + # parallel + if self.getOrder(event,first) == 1: + parallel.append(event.run) + return parallel + + def getRun(self,runid): + for run in self.runs: + if run.id == runid: + return run + return None + +class ProtocolDescription(object): + def __init__(self,protocol): + self.protocol = protocol + self.roledescr = {} + + # Find event by label + def findEvent(self,eventlabel,eventType=None): + for (role,descr) in self.roledescr.items(): + for event in descr: + if event.label == eventlabel: + if eventType == None or isinstance(event,eventType): + return event + + # Return all events that should have occured before the given event + # if the protocol is executed exactly as specified + # (i.e. all previous events in the same run and the preceding events + # of the matching sends of all reads) + def getPrecedingEvents(self,eventlabel,eventType=None): + event = self.findEvent(eventlabel,eventType) + if event.preceding != None: + return event.preceding + preceding = event.getBefore()+[event] + for prev in preceding: + # For this event and all events that are before it in the run + # description see if it is a read and if it is also add the + # precedinglabelset of the matching send + if (isinstance(prev,EventRead)): + match = self.findEvent(prev.label,EventSend) + if match: + preceding.extend(self.getPrecedingEvents(match.label,EventSend)) + preceding = uniq(preceding) + event.preceding = preceding + return preceding + + # Calculate the preceding labelset that is all read events + # that are in the precedingEvents of a certain event + def getPrecedingLabelSet(self,eventlabel): + events = self.getPrecedingEvents(eventlabel) + events = filter(lambda x: isinstance(x,EventRead),events) + return [x.label for x in events] + + # Calculate the roles in preceding labelset that is all roles that + # that are in the precedingEvents of a certain event + def getPrecedingRoleSet(self,eventlabel): + events = self.getPrecedingEvents(eventlabel) + roles = uniq([x.run.role for x in events]) + return roles + + + def __str__(self): + s = '' + for x in self.roledescr.values(): + for e in x: + s += str(e) + "\n" + return s + +class Run(object): + def __init__(self): + self.id = None + self.protocol = None + self.role = None + self.roleAgents = {} + self.eventList = [] + self.intruder = False + self.attack = None + self.variables = [] + + def __iter__(self): + return iter(self.eventList) + + def getAgent(self): + if self.intruder: + return None + return self.roleAgents[self.role] + + def getFirstAction(self): + return self.eventList[0] + + def getLastAction(self): + return self.eventList[-1] + + def collapseIntruder(self): + """ TODO still working on this. """ + if self.intruder: + shouldcollapse = False + for ev in self: + return + +class Event(object): + def __init__(self,index,label,follows): + self.index = index + self.label = label + self.follows = follows + self.run = None + self.preceding = None + self.rank = None + + def shortLabel(self): + try: + return self.label[len(self.label)-1] + except: + return str(self.label) + + def getBefore(self): + result = [] + for event in self.run: + if (event == self): + return result + result.append(event) + # This should never happen + assert(False) + +class EventSend(Event): + def __init__(self,index,label,follows,fr,to,message): + Event.__init__(self,index,label,follows) + self.fr = fr + self.to = to + self.message = message + + def __str__(self): + if self.run.intruder: + return "SEND(%s)" % self.message + else: + return "SEND_%s(%s,%s)" % (self.shortLabel(),self.to,self.message) + +class EventRead(Event): + def __init__(self,index,label,follows,fr,to,message): + Event.__init__(self,index,label,follows) + self.fr = fr + self.to = to + self.message = message + + def __str__(self): + if self.run.intruder: + return "READ(%s)" % self.message + else: + return "READ_%s(%s,%s)" % (self.shortLabel(),self.fr, self.message) + +class EventClaim(Event): + def __init__(self,index,label,follows,role,type,argument): + Event.__init__(self,index,label,follows) + self.role = role + self.type = type + self.argument = argument + self.broken = None + + # A Claim should be ignored if there is an untrusted agent in the role + # agents + def ignore(self): + for untrusted in self.run.attack.untrusted: + if untrusted in self.run.roleAgents.values(): + return True + return False + + # Return (protocol,role) + def protocolRole(self): + return "(%s,%s)" % (self.run.protocol,self.run.role) + + def argstr(self): + if self.argument == None: + return '*' + else: + return str(self.argument) + + def __str__(self): + return "CLAIM_%s(%s, %s)" % (self.shortLabel(),self.type,self.argstr()) + +class EventIntruder(Event): + """ + Intruder event extensions (allows for collapsing attacks later) + """ + def __init__(self,follows,message,key,result): + Event.__init__(self,0,None,follows) + self.follows = follows + self.message = message + self.key = key + self.result = result + self.intruder = True + +class EventDecr(EventIntruder): + def __str__(self): + return "DECR(%s, %s, %s)" % (self.message, self.key, self.result) + +class EventEncr(EventIntruder): + def __str__(self): + return "ENCR(%s, %s, %s)" % (self.message, self.key, self.result) + + diff --git a/Vagrant Files/files/scyther/Scyther/XMLReader.py b/Vagrant Files/files/scyther/Scyther/XMLReader.py new file mode 100644 index 0000000..ebafc47 --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/XMLReader.py @@ -0,0 +1,357 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# XMLReader +# +# Note: +# This requires python elementtree to work +# See: http://effbot.org/zone/element-index.htm +# +# On Fedora Core you can install this by installing the python-elementtree rpm +# Things will be a lot faster and consume less memory if you install the +# cElementTree module +# +# In python 2.5 cElementTree is in the core, so you don't need to install +# extra packages +# + +import sys + +# Check for cElementTree presence. Otherwise use ElementTree. +useiter = True +try: + # python 2.5 has cElementTree in the core + import xml.etree.cElementTree as cElementTree +except: + # try the old way + try: + import cElementTree + except ImportError: + useiter = False + try: + from elementtree import ElementTree + except ImportError: + print """ +ERROR: + +Could not locate either the [elementtree] or the [cElementTree] package. +Please install one of them in order to work with the Scyther python interface. +The [cElementTree] packages can be found at http://effbot.org/zone/celementtree.htm + +Note that you can still use the Scyther binaries in the 'Bin' directory. + """ + sys.exit(1) + +## Simply pick cElementTree +#import cElementTree +## Simply pick ElementTree +#useiter = False +#from elementtree import ElementTree + +import Term +import Attack +import Trace +import Claim + +class XMLReader(object): + + def __init__ (self): + self.varlist = [] + pass + + def readXML(self, input): + # Use iter parse when possble so we can clear the attack after reading + # it in order to preserve memory (this requires cElementTree) + + attackbuffer = [] + claims = [] + + if useiter: + parser = cElementTree.iterparse(input) + else: + parser = ElementTree.parse(input).findall('*') + + for elem in parser: + # The iter parser receives the input in tuples (event and element) + # we only need the event + if useiter: + elem = elem[1] + + if elem.tag == 'state': + attack = self.readAttack(elem) + attackbuffer.append(attack) + if useiter: + elem.clear() + + if elem.tag == 'claimstatus': + claim = self.readClaim(elem) + claim.attacks = attackbuffer + claims.append(claim) + + # link to parent + for attack in claim.attacks: + attack.claim = claim + + attackbuffer = [] + if useiter: + elem.clear() + + return claims + + # Read a term from XML + def readTerm(self,xml): + # If xml is None the term should also be none + if xml == None: + return None + # If this is a term variable read it directly + if (xml.tag in ('tuple','const','apply','encrypt','var')): + return self.readSubTerm(xml) + # Otherwise read from it's first child + children = xml.getchildren() + assert(len(children) == 1) + return self.readSubTerm(children[0]) + + def readSubTerm(self, tag): + if tag.tag == 'tuple': + return Term.TermTuple(self.readTerm(tag.find('op1')),self.readTerm(tag.find('op2'))) + elif tag.tag == 'const': + return Term.TermConstant(tag.text) + elif tag.tag == 'apply': + return Term.TermApply(self.readTerm(tag.find('function')),self.readTerm(tag.find('arg'))) + elif tag.tag == 'encrypt': + return Term.TermEncrypt(self.readTerm(tag.find('op')),self.readTerm(tag.find('key'))) + elif tag.tag == 'var': + name = Term.TermConstant(tag.get('name')) + # Instantiate this variable if possible (note this list is empty while reading + # the variables section of the XML file) + for inst in self.varlist: + if inst.name == name: + return inst + # If it is not instantiated in varlist, just return a variable with this name and no + # value + return Term.TermVariable(name,None) + else: + raise Term.InvalidTerm, "Invalid term type in XML: %s" % tag.tag + + def readEvent(self,xml): + label = self.readTerm(xml.find('label')) + follows = xml.findall('follows') + followlist = [] + for follow in follows: + follow = follow.find('after') + if follow == None: + # Ignore follow definitions that do not contain after + continue + follow = (int(follow.get('run')),int(follow.get('index'))) + followlist.append(follow) + + (etype,index) = (xml.get('type'),int(xml.get('index'))) + if etype in ('send','read','recv'): + fr = self.readTerm(xml.find('from')) + to = self.readTerm(xml.find('to')) + message = self.readTerm(xml.find('message')) + if (etype == 'send'): + return Trace.EventSend(index,label,followlist,fr,to,message) + else: + return Trace.EventRead(index,label,followlist,fr,to,message) + elif xml.get('type') == 'claim': + role = self.readTerm(xml.find('role')) + etype = self.readTerm(xml.find('type')) + argument = self.readTerm(xml.find('argument')) + # Freshness claims are implemented as Empty claims with + # (Fresh,Value) as arguments + try: + if etype == 'Empty' and argument[0] == 'Fresh': + etype = Term.TermConstant('Fresh') + argument = argument[1] + elif etype == 'Empty' and argument[0] == 'Compromised': + etype = Term.TermConstant('Compromised') + argument = argument[1] + except: + pass + return Trace.EventClaim(index,label,followlist,role,etype,argument) + else: + raise Trace.InvalidAction, "Invalid action in XML: %s" % (xml.get('type')) + + def readRun(self,xml): + assert(xml.tag == 'run') + run = Trace.Run() + run.id = int(xml.find('runid').text) + # TODO why is protocol name a term?? + run.protocol = str(self.readTerm(xml.find('protocol'))) + run.intruder = xml.find('protocol').get('intruder') == 'true' + run.role = xml.find('rolename').text + for role in xml.find('roleagents'): + name = role.find('rolename').text + agent = self.readTerm(role.find('agent')) + run.roleAgents[name] = agent + for eventxml in xml.find('eventlist'): + action = self.readEvent(eventxml) + action.run = run + run.eventList.append(action) + for variable in xml.find('variables'): + # Read the variables one by one + assert(variable.tag == 'variable') + var = self.readTerm(variable.find('name').find('term')) + var.types = self.readTypeList(variable.find('name')) + + substxml = variable.find('substitution') + # Read substitution if present + if substxml != None: + subst = self.readTerm(substxml.find('term')) + subst.types = self.readTypeList(substxml) + newvar = Term.TermVariable(var.name,subst) + newvar.types = var.types + var = newvar + + run.variables.append(var) + return run + + # Read protocol description for a certain role + def readRoleDescr(self,xml): + assert(xml.tag == 'role') + run = Trace.Run() + # We will need the last label later on to see if a + # run is complete + run.lastLabel = None + run.role = xml.find('rolename').text + for eventxml in xml.find('eventlist'): + action = self.readEvent(eventxml) + action.run = run + run.eventList.append(action) + run.lastLabel = action.label + return run + + def readTypeList(self,xml): + result = [] + vartypes = xml.find('type').find('termlist') + for vartype in vartypes: + # We will assume that types are simple strings + result.append(str(self.readTerm(vartype))) + return result + + def readClaim(self, xml): + claim = Claim.Claim() + for event in xml.getchildren(): + if event.tag == 'claimtype': + claim.claimtype = self.readTerm(event) + elif event.tag == 'label': + # We store the full protocol,label construct for + # consistency with the technical parts, so it is left to + # the __str__ of claim to select the right element + claim.label = self.readTerm(event) + elif event.tag == 'protocol': + claim.protocol = self.readTerm(event) + elif event.tag == 'role': + claim.role = self.readTerm(event) + elif event.tag == 'parameter': + claim.parameter = self.readTerm(event) + + elif event.tag == 'failed': + claim.failed = int(event.text) + elif event.tag == 'count': + claim.count = int(event.text) + elif event.tag == 'states': + claim.states = int(event.text) + + elif event.tag == 'complete': + claim.complete = True + elif event.tag == 'timebound': + claim.timebound = True + else: + print >>sys.stderr,"Warning unknown tag in claim: %s" % claim.tag + + claim.analyze() + return claim + + def readAttack(self, xml): + self.varlist = [] + attack = Attack.Attack() + attack.id = int(xml.get('id')) + # A state contains 4 direct child nodes: + # broken, system, variables and semitrace + # optionally a fifth: dot + for event in xml.getchildren(): + if event.tag == 'broken': + attack.broken.append((self.readTerm(event.find('claim')), + self.readTerm(event.find('label')))) + elif event.tag == 'system': + attack.match = int(event.find('match').text) + for term in event.find('commandline'): + if attack.commandline != '': + attack.commandline += ' ' + attack.commandline += term.text + for term in event.find('untrusted').find('termlist'): + attack.untrusted.append(str(self.readTerm(term))) + for term in event.find('initialknowledge').find('termlist'): + attack.initialKnowledge.append(self.readTerm(term)) + for keypair in event.find('inversekeys'): + inverse = [] + for term in keypair: + inverse.append(self.readTerm(term)) + assert(len(inverse) == 0 or len(inverse) == 2) + attack.inverseKeys.append(inverse) + # TODO why is protocol name a term?? + for protocolxml in event.findall('protocol'): + protocol = str(self.readTerm(protocolxml.find('name'))) + descr = Trace.ProtocolDescription(protocol) + attack.protocoldescr[protocol] = descr + for rolexml in protocolxml.findall('role'): + roledescr = self.readRoleDescr(rolexml) + descr.roledescr[roledescr.role] = roledescr + + elif event.tag == 'semitrace': + for runxml in event: + run = self.readRun(runxml) + run.attack = attack + attack.semiTrace.runs.append(run) + + elif event.tag == 'dot': + # Apparently Scyther already generated dot output, + # store + attack.scytherDot = event.text + + elif event.tag == 'variables': + # Read the variables one by one + for varxml in event: + if varxml.get('typeflaw') == 'true': + attack.typeflaws = True + var = self.readTerm(varxml.find('name').find('term')) + var.types = self.readTypeList(varxml.find('name')) + + substxml = varxml.find('substitution') + # Read substitution if present + if substxml != None: + subst = self.readTerm(substxml.find('term')) + subst.types = self.readTypeList(substxml) + newvar = Term.TermVariable(var.name,subst) + newvar.types = var.types + var = newvar + + attack.variables.append(var) + + # When all have been read set self.varlist so that when + # we read terms in the attacks they can be filled in using + # this list + self.varlist = attack.variables + else: + print >>sys.stderr,"Warning unknown tag in attack: %s" % event.tag + return attack + diff --git a/Vagrant Files/files/scyther/Scyther/__init__.py b/Vagrant Files/files/scyther/Scyther/__init__.py new file mode 100644 index 0000000..1fa659c --- /dev/null +++ b/Vagrant Files/files/scyther/Scyther/__init__.py @@ -0,0 +1,29 @@ +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# Init this module +# +# Set prefix for __all__ +# +import Scyther + +# Provide scope +__all__ = ["Scyther"] + diff --git a/Vagrant Files/files/scyther/Time/test.py b/Vagrant Files/files/scyther/Time/test.py new file mode 100644 index 0000000..50ea49e --- /dev/null +++ b/Vagrant Files/files/scyther/Time/test.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2008 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# test.py +# experimenting with the constraint solver +# +# Ubuntu package: python-constraint +# +# http://labix.org/python-constraint +# + +#--------------------------------------------------------------------------- + +""" Import externals """ +import sys +try: + from constraint import * +except: + print "Could not import constraint solver module." + print "For more information, visit" + print " http://labix.org/python-constraint" + sys.exit() + +#--------------------------------------------------------------------------- + +def test(): + problem = Problem() + problem.addVariables(range(0, 16), range(1, 16+1)) + problem.addConstraint(AllDifferentConstraint(), range(0, 16)) + problem.addConstraint(ExactSumConstraint(34), [0,5,10,15]) + problem.addConstraint(ExactSumConstraint(34), [3,6,9,12]) + for row in range(4): + problem.addConstraint(ExactSumConstraint(34), + [row*4+i for i in range(4)]) + for col in range(4): + problem.addConstraint(ExactSumConstraint(34), + [col+4*i for i in range(4)]) + solutions = problem.getSolutions() + print solutions + +#--------------------------------------------------------------------------- + +if __name__ == '__main__': + test() + diff --git a/Vagrant Files/files/scyther/batcher.sh b/Vagrant Files/files/scyther/batcher.sh new file mode 100644 index 0000000..6b430d3 --- /dev/null +++ b/Vagrant Files/files/scyther/batcher.sh @@ -0,0 +1,46 @@ +#!/bin/sh +# +# batcher.sh +# +# usage: ./batcher.sh TEST_MPA_ARGUMENTS +# +# Tries to parallellize the jobs, and sends a mail afterwards + +echo "=================================" +echo " Phase 0: Setup" +echo "=================================" +AWKSCRIPT=" { srand(); print int(1000000 * rand()) } " +RND=`echo | awk "$AWKSCRIPT"` + +JOBNAME="test$RND" +JSONFILE="$PWD/$JOBNAME.json" +BATCHFILE="$PWD/$JOBNAME.sh" + +echo $JOBNAME +echo $JSONFILE +echo $BATCHFILE + +echo "=================================" +echo " Phase 1: generate jobs list" +echo "=================================" +bsub -I -N -W 8:00 -J $JOBNAME ./test-mpa.py --pickle $JSONFILE $* + +echo "=================================" +echo " Phase 2a: precompute job outputs" +echo "=================================" +# Each verification has a time limit of 600 seconds = 10 minutes +# To fit in the one hour queue, that means 5 jobs maximum. +bsub -I -N -W 8:00 -J $JOBNAME -oo $BATCHFILE ./make-bsub.py $JSONFILE 5 -W 1:00 -J $JOBNAME +# Due to pending etc. the below may take a while. +sleep 10 +bash $BATCHFILE +echo "=================================" +echo " Phase 2b: perfom actual job" +echo " (after precomputation is done" +echo "=================================" +bsub -I -N -W 8:00 -J after$JOBNAME -w "ended($JOBNAME)" ./test-mpa.py $* + + +echo "=================================" +echo " Done." +echo "=================================" diff --git a/Vagrant Files/files/scyther/combos-book.sh b/Vagrant Files/files/scyther/combos-book.sh new file mode 100644 index 0000000..888db45 --- /dev/null +++ b/Vagrant Files/files/scyther/combos-book.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +bsub -W 8:00 -Jd "book-aa-t" -N ./test-mpa.py -m 2 --plain --latex book-aa-t Protocols/MultiProtocolAttacks/*.spdl +bsub -W 8:00 -Jd "book-aa-b" -N ./test-mpa.py -m 2 --plain -b --latex book-aa-b Protocols/MultiProtocolAttacks/*.spdl +bsub -W 8:00 -Jd "book-aa-u" -N ./test-mpa.py -m 2 --plain -u --latex book-aa-u Protocols/MultiProtocolAttacks/*.spdl +bsub -W 8:00 -Jd "book-ex-t" -N ./test-mpa.py -m 2 --plain --extravert --latex book-ex-t Protocols/MultiProtocolAttacks/*.spdl +bsub -W 8:00 -Jd "book-ex-b" -N ./test-mpa.py -m 2 --plain -b --extravert --latex book-ex-b Protocols/MultiProtocolAttacks/*.spdl +bsub -W 8:00 -Jd "book-ex-u" -N ./test-mpa.py -m 2 --plain -u --extravert --latex book-ex-u Protocols/MultiProtocolAttacks/*.spdl +bsub -W 8:00 -Jd "book-iu-t" -N ./test-mpa.py -m 2 --plain --init-unique --latex book-iu-t Protocols/MultiProtocolAttacks/*.spdl +bsub -W 8:00 -Jd "book-iu-b" -N ./test-mpa.py -m 2 --plain -b --init-unique --latex book-iu-b Protocols/MultiProtocolAttacks/*.spdl +bsub -W 8:00 -Jd "book-iu-u" -N ./test-mpa.py -m 2 --plain -u --init-unique --latex book-iu-u Protocols/MultiProtocolAttacks/*.spdl diff --git a/Vagrant Files/files/scyther/combos-ike.sh b/Vagrant Files/files/scyther/combos-ike.sh new file mode 100644 index 0000000..515b20e --- /dev/null +++ b/Vagrant Files/files/scyther/combos-ike.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# Individual data +./combos-ikev1.sh +./combos-ikev2.sh + +# And combine +./combos-ikev0.sh diff --git a/Vagrant Files/files/scyther/combos-ikev0.sh b/Vagrant Files/files/scyther/combos-ikev0.sh new file mode 100644 index 0000000..389835b --- /dev/null +++ b/Vagrant Files/files/scyther/combos-ikev0.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +bsub -W 8:00 -Jd "ike0-aa-t" -N ./test-mpa.py -m 2 --plain --latex ike0-aa-t ~/src/ikev2/pp-results/mpa/ikev*.spdl +bsub -W 8:00 -Jd "ike0-aa-b" -N ./test-mpa.py -m 2 --plain -b --latex ike0-aa-b ~/src/ikev2/pp-results/mpa/ikev*.spdl +bsub -W 8:00 -Jd "ike0-aa-u" -N ./test-mpa.py -m 2 --plain -u --latex ike0-aa-u ~/src/ikev2/pp-results/mpa/ikev*.spdl +bsub -W 8:00 -Jd "ike0-ex-t" -N ./test-mpa.py -m 2 --plain --extravert --latex ike0-ex-t ~/src/ikev2/pp-results/mpa/ikev*.spdl +bsub -W 8:00 -Jd "ike0-ex-b" -N ./test-mpa.py -m 2 --plain -b --extravert --latex ike0-ex-b ~/src/ikev2/pp-results/mpa/ikev*.spdl +bsub -W 8:00 -Jd "ike0-ex-u" -N ./test-mpa.py -m 2 --plain -u --extravert --latex ike0-ex-u ~/src/ikev2/pp-results/mpa/ikev*.spdl +bsub -W 8:00 -Jd "ike0-iu-t" -N ./test-mpa.py -m 2 --plain --init-unique --latex ike0-iu-t ~/src/ikev2/pp-results/mpa/ikev*.spdl +bsub -W 8:00 -Jd "ike0-iu-b" -N ./test-mpa.py -m 2 --plain -b --init-unique --latex ike0-iu-b ~/src/ikev2/pp-results/mpa/ikev*.spdl +bsub -W 8:00 -Jd "ike0-iu-u" -N ./test-mpa.py -m 2 --plain -u --init-unique --latex ike0-iu-u ~/src/ikev2/pp-results/mpa/ikev*.spdl + diff --git a/Vagrant Files/files/scyther/combos-ikev1.sh b/Vagrant Files/files/scyther/combos-ikev1.sh new file mode 100644 index 0000000..a5743b9 --- /dev/null +++ b/Vagrant Files/files/scyther/combos-ikev1.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +bsub -W 8:00 -Jd "ike1-aa-t" -N ./test-mpa.py -m 2 --plain --latex ike1-aa-t ~/src/ikev2/pp-results/mpa/ikev1*.spdl +bsub -W 8:00 -Jd "ike1-aa-b" -N ./test-mpa.py -m 2 --plain -b --latex ike1-aa-b ~/src/ikev2/pp-results/mpa/ikev1*.spdl +bsub -W 8:00 -Jd "ike1-aa-u" -N ./test-mpa.py -m 2 --plain -u --latex ike1-aa-u ~/src/ikev2/pp-results/mpa/ikev1*.spdl +bsub -W 8:00 -Jd "ike1-ex-t" -N ./test-mpa.py -m 2 --plain --extravert --latex ike1-ex-t ~/src/ikev2/pp-results/mpa/ikev1*.spdl +bsub -W 8:00 -Jd "ike1-ex-b" -N ./test-mpa.py -m 2 --plain -b --extravert --latex ike1-ex-b ~/src/ikev2/pp-results/mpa/ikev1*.spdl +bsub -W 8:00 -Jd "ike1-ex-u" -N ./test-mpa.py -m 2 --plain -u --extravert --latex ike1-ex-u ~/src/ikev2/pp-results/mpa/ikev1*.spdl +bsub -W 8:00 -Jd "ike1-iu-t" -N ./test-mpa.py -m 2 --plain --init-unique --latex ike1-iu-t ~/src/ikev2/pp-results/mpa/ikev1*.spdl +bsub -W 8:00 -Jd "ike1-iu-b" -N ./test-mpa.py -m 2 --plain -b --init-unique --latex ike1-iu-b ~/src/ikev2/pp-results/mpa/ikev1*.spdl +bsub -W 8:00 -Jd "ike1-iu-u" -N ./test-mpa.py -m 2 --plain -u --init-unique --latex ike1-iu-u ~/src/ikev2/pp-results/mpa/ikev1*.spdl + diff --git a/Vagrant Files/files/scyther/combos-ikev2.sh b/Vagrant Files/files/scyther/combos-ikev2.sh new file mode 100644 index 0000000..1da0bb1 --- /dev/null +++ b/Vagrant Files/files/scyther/combos-ikev2.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +bsub -W 8:00 -Jd "ike2-aa-t" -N ./test-mpa.py -m 2 --plain --latex ike2-aa-t ~/src/ikev2/pp-results/mpa/ikev2*.spdl +bsub -W 8:00 -Jd "ike2-aa-b" -N ./test-mpa.py -m 2 --plain -b --latex ike2-aa-b ~/src/ikev2/pp-results/mpa/ikev2*.spdl +bsub -W 8:00 -Jd "ike2-aa-u" -N ./test-mpa.py -m 2 --plain -u --latex ike2-aa-u ~/src/ikev2/pp-results/mpa/ikev2*.spdl +bsub -W 8:00 -Jd "ike2-ex-t" -N ./test-mpa.py -m 2 --plain --extravert --latex ike2-ex-t ~/src/ikev2/pp-results/mpa/ikev2*.spdl +bsub -W 8:00 -Jd "ike2-ex-b" -N ./test-mpa.py -m 2 --plain -b --extravert --latex ike2-ex-b ~/src/ikev2/pp-results/mpa/ikev2*.spdl +bsub -W 8:00 -Jd "ike2-ex-u" -N ./test-mpa.py -m 2 --plain -u --extravert --latex ike2-ex-u ~/src/ikev2/pp-results/mpa/ikev2*.spdl +bsub -W 8:00 -Jd "ike2-iu-t" -N ./test-mpa.py -m 2 --plain --init-unique --latex ike2-iu-t ~/src/ikev2/pp-results/mpa/ikev2*.spdl +bsub -W 8:00 -Jd "ike2-iu-b" -N ./test-mpa.py -m 2 --plain -b --init-unique --latex ike2-iu-b ~/src/ikev2/pp-results/mpa/ikev2*.spdl +bsub -W 8:00 -Jd "ike2-iu-u" -N ./test-mpa.py -m 2 --plain -u --init-unique --latex ike2-iu-u ~/src/ikev2/pp-results/mpa/ikev2*.spdl + + diff --git a/Vagrant Files/files/scyther/combos-iso.sh b/Vagrant Files/files/scyther/combos-iso.sh new file mode 100644 index 0000000..b9fb250 --- /dev/null +++ b/Vagrant Files/files/scyther/combos-iso.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +bsub -W 8:00 -Jd "iso-aa-t" -N ./test-mpa.py -m 2 --plain --latex iso-aa-t ~/papers/iso9798/scyther-models/*.spdl +bsub -W 8:00 -Jd "iso-aa-b" -N ./test-mpa.py -m 2 --plain -b --latex iso-aa-b ~/papers/iso9798/scyther-models/*.spdl +bsub -W 8:00 -Jd "iso-aa-u" -N ./test-mpa.py -m 2 --plain -u --latex iso-aa-u ~/papers/iso9798/scyther-models/*.spdl +bsub -W 8:00 -Jd "iso-ex-t" -N ./test-mpa.py -m 2 --plain --extravert --latex iso-ex-t ~/papers/iso9798/scyther-models/*.spdl +bsub -W 8:00 -Jd "iso-ex-b" -N ./test-mpa.py -m 2 --plain -b --extravert --latex iso-ex-b ~/papers/iso9798/scyther-models/*.spdl +bsub -W 8:00 -Jd "iso-ex-u" -N ./test-mpa.py -m 2 --plain -u --extravert --latex iso-ex-u ~/papers/iso9798/scyther-models/*.spdl +bsub -W 8:00 -Jd "iso-iu-t" -N ./test-mpa.py -m 2 --plain --init-unique --latex iso-iu-t ~/papers/iso9798/scyther-models/*.spdl +bsub -W 8:00 -Jd "iso-iu-b" -N ./test-mpa.py -m 2 --plain -b --init-unique --latex iso-iu-b ~/papers/iso9798/scyther-models/*.spdl +bsub -W 8:00 -Jd "iso-iu-u" -N ./test-mpa.py -m 2 --plain -u --init-unique --latex iso-iu-u ~/papers/iso9798/scyther-models/*.spdl diff --git a/Vagrant Files/files/scyther/generate-attack-graphs.py b/Vagrant Files/files/scyther/generate-attack-graphs.py new file mode 100644 index 0000000..bad12b1 --- /dev/null +++ b/Vagrant Files/files/scyther/generate-attack-graphs.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +""" +Generate attacks for each claim + +To also generate resource usage details on linux, use something like: + + xargs -a protocols.txt -n 1 -I {} /usr/bin/time -v -o {}.times ./generate-attack-graphs.py {} + +where 'protocols.txt' contains a protocol file per line. +""" + +#--------------------------------------------------------------------------- + +""" Import externals """ +import sys + +#--------------------------------------------------------------------------- + +""" Import scyther components """ +import Scyther.Scyther as Scyther + +#--------------------------------------------------------------------------- + +def create_file_prefix(fn,cid): + """ + Create a filename prefix for fn,cid without extension + """ + + tcid = cid + i = tcid.rfind(",") + if i > 0: + if fn.find(tcid[:i]) >= 0: + tcid = tcid[i+1:] + + tfn = fn.replace(".spdl","") + i = tfn.rfind("/") + if i >= 0: + tfn = tfn[i+1:] + + pref = "%s-%s" % (tfn,tcid) + pref = pref.replace(",","_") + + return pref + + +def render_dot(fn,gtype): + """ + Render .dot file called fn into gtype file + """ + from subprocess import call + + if len(gtype) > 5: + # Something is fishy, abort + return + + base_name = fn + i = base_name.rfind(".") + if i > 0: + base_name = base_name[:i] + + cmd = ["dot","-T" + gtype,"-o%s.%s" % (base_name,gtype),fn] + #print cmd + + call(cmd) + + +def render_best_attack(fn,cid): + """ + Extract the best attack for this claim and file name + """ + x = Scyther.Scyther() + x.setFile(fn) + + x.options = "-r4 -T60" + x.verifyOne(cid) + + pref = create_file_prefix(fn,cid) + + for cl in x.claims: + cln = cl.claimtype + if cln == "Commit": + cln = "Data_agree" + + if len(cl.attacks) > 0: + dotfile = "attack-%s-%s.dot" % (pref,cln) + fp = open(dotfile,'w') + fp.write(cl.attacks[-1].scytherDot) + fp.close() + + render_dot(dotfile,"png") + render_dot(dotfile,"pdf") + + print "%s; %s" % (fn,cl) + +def main(): + + filelist = sys.argv[1:] + # Compute dict of filenames to claim id's + cl = Scyther.GetClaims(filelist) + + for fn in set(cl): + for cid in cl[fn]: + + render_best_attack(fn,cid) + + + +if __name__ == '__main__': + main() + +#--------------------------------------------------------------------------- +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/json-scyther.py b/Vagrant Files/files/scyther/json-scyther.py new file mode 100644 index 0000000..b8e23bd --- /dev/null +++ b/Vagrant Files/files/scyther/json-scyther.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +""" + +Author: Cas Cremers + +""" + +import sys +import json +from Scyther import Scyther + + +def scyther_json(jsondata): + """ + Decode json data into (protocollist,options,filter) and run scyther + """ + s = Scyther.Scyther() + + (protocollist,options,filter) = json.loads(jsondata) + + s.options = str(options) + for protocol in sorted(protocollist): + s.addFile(protocol) + s.verifyOne(str(filter)) + +def fileandline(fn,linenos): + fp = open(fn,"r") + ln = 1 + done = 0 + sz = len(linenos) + for l in fp.xreadlines(): + if str(ln) in linenos: + print l + scyther_json(l) + done = done + 1 + if done >= sz: + fp.close() + return + ln = ln + 1 + fp.close() + return + +if __name__ == '__main__': + fileandline(sys.argv[1],set(sys.argv[2:])) + + diff --git a/Vagrant Files/files/scyther/make-bsub.py b/Vagrant Files/files/scyther/make-bsub.py new file mode 100644 index 0000000..0897da1 --- /dev/null +++ b/Vagrant Files/files/scyther/make-bsub.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# +import sys +import json +import math + +""" +Given a file of Scyther verification tests to do (json file), create a shell file to run them all using bsub. + +Arguments: + + [1] Filename of json stuff + [2] Step count: how many verification tasks go into one job + [3] Additional commands to send to bsub (e.g. "-W 1:00") + +""" + +def countlines(fn): + count = 0 + fh = open(fn,'r') + for l in fh.xreadlines(): + count = count + 1 + fh.close() + return count + +def marker(jobcount,todo): + left = todo - jobcount + dperc = int((100 * jobcount) / todo) + print "echo \"Sent %i out of %i jobs, hence %i left. %i%% done.\"" % (jobcount,todo,left,dperc) + +def main(fn,step,optlist): + + todo = math.ceil(countlines(fn) / int(step)) + + fh = open(fn,'r') + ln = 1 + buf = 0 + s = "" + jobcount = 0 + done = 0 + + for l in fh.xreadlines(): + if buf == 0: + s = "bsub %s ./json-scyther.py %s" % (" ".join(optlist),fn) + s += " %i" % (ln) + buf = buf + 1 + done = done + 1 + if buf >= int(step): + print (s) + s = "" + buf = 0 + jobcount = jobcount + 1 + if jobcount % 10 == 0: + """ + After ten jobs, display progress info + """ + marker(jobcount,todo) + + ln = ln + 1 + print (s) + marker(jobcount,todo) + fh.close() + + +if __name__ == '__main__': + """ Usage: filename, step, options to send to bsub + """ + main(sys.argv[1],sys.argv[2],sys.argv[3:]) + diff --git a/Vagrant Files/files/scyther/mpa.spdl b/Vagrant Files/files/scyther/mpa.spdl new file mode 100644 index 0000000..4913029 --- /dev/null +++ b/Vagrant Files/files/scyther/mpa.spdl @@ -0,0 +1,79 @@ +/* + * Needham-Schroeder-Lowe protocol + */ + +// The protocol description + +protocol nsl3(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {ni,I}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {ni,I}pk(R) ); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} + +/* + * Needham-Schroeder-Lowe protocol, + * broken version (wrong role name in first message) + */ + +// The protocol description + +protocol nsl3-broken(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {ni,R}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {ni,R}pk(R) ); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/notes-brutus-mpa.txt b/Vagrant Files/files/scyther/notes-brutus-mpa.txt new file mode 100644 index 0000000..b89e393 --- /dev/null +++ b/Vagrant Files/files/scyther/notes-brutus-mpa.txt @@ -0,0 +1,181 @@ +run test-MPA with --pickle to some file FILE. + +Choose a STEP integer: how many verifications are batched into a single job. + +Then: + +./make-bsub.py FILE STEP -W 1:00 [OTHER BSUB OPTIONS] > tests.sh + +Then + +bash tests.sh + + +When all is done, rerun the original thing without pickle. + + + +This invokes then: +json-scyther.py +in different batches + + + + + +Test run for real + + +Fri Dec 31 16:33:20 CET 2010 + +Login & screen on brutus3 node. + +bsub -W 2:00 ./test-mpa.py --pickle mpa-tests.json -A Protocols/MultiProtocolAttacks/*.spdl + +Fri Dec 31 18:48:29 CET 2010 + +Given the 6 minutes timeout, decided to batch into the 1h queues. Thus 9 +verifications can safely go in a batch. + +./make-bsub.py mpa-tests.json 9 -W 1:00 >mpa-tests.sh + +bash mpa-tests.sh + + +Hmm. For the 1h queue on Brutus, there is a 10.000 pending jobs limit. Thus my +40.000+ jobs get stuck here. + +So I could have done the division such that the jobs can be pended at onces +but it would have meant putting the jobs in the 8h or more queues. + +For the batching thing, it would be nice to print a counter every 10 bsubs so +if it gets stuck, you can see where it is (or better: how much is left). + +The lsf.o* output files clog up the directory. Find a way to disable them! + +Woops, we get mail once in a while. Not good. Unclear under which conditions +this occurs, it seems to be errors only. (Probably stale file pointers from +the old watch & rm solution.) + +Sun Jan 2 10:54:23 CET 2011 + +All jobs have been submitted, now only 3000 pending. + +There may be a limit for me of about 128 active jobs at the same time. + +Sun Jan 2 11:30:30 CET 2011 + +2200 pending. + +Sun Jan 2 12:38:48 CET 2011 + +1155 pending. +(bjobs -p | grep PEND | wc -l) + +Sun Jan 2 13:59:04 CET 2011 + +0 jobs pending, 32 jobs active. + +Sun Jan 2 14:18:11 CET 2011 + +Done. Recomp started (without --pickle FILE above) +Takes too long on login node. Killed at 14:40. + +Instead, rerunning with: + +bsub -I -N ./test-mpa.py -A Protocols/MultiProtocolAttacks/*.spdl + +-I for interactive, -N for mail at end. + +Sun Jan 2 14:45:04 CET 2011 + +Above job is running. It also seems faster. + +Sun Jan 2 20:07:58 CET 2011 + +Sigh. It got killed after one hour because no time limit was set. +Rerunning with -W 6:00 + + + + + + +Sun Jan 2 14:30:19 CET 2011 + +In parallel, starting new huge job; biggest possible using current script options. + +bsub -W 7:00 ./test-mpa.py --pickle test-full-mpa.json --self-communication -A Protocols/MultiProtocolAttacks/*.spdl + +Actually, these big jobs should be started with finishing e-mail notification +or the switch that makes the bsub command only return after the jobs has +finished, otherwise we end up watching bjobs all the time, which is boring. + +Sun Jan 2 14:40:08 CET 2011 + +The above test generation is now running. + +Sun Jan 2 20:09:42 CET 2011 + +The test generation seems to have finished at 15:31. + +./make-bsub.py test-full-mpa.json 10 -W 1:00 >test-full-mpa.sh + +This finished at 20:11. +So now running + +nice bash test-full-mpa.sh + +G + + + +Sun Jan 2 15:07:13 CET 2011 + +A third parallel test: + +batcher.sh OPTIONS_AND_FILES_FOR_TEST_MPA_SCRIPT + +Running with -L5. This should automate all of the previous stuff. + + + + +Wed Jan 5 15:37:11 CET 2011 + +Running for cryptrec (with new Scyther version and new batches of 5 things) +./batcher.sh ~/papers/iso/*.spdl + + + +Tue Jan 18 17:10:49 CET 2011 + +./batcher.sh -m 1 --all-types --self-communication ~/papers/iso/*.spdl +The batcher has jobid 930582 + +(error, reverting to os.makedirs(path)) + +Tue Jan 18 23:45:15 CET 2011 + +./test-iso-combo.sh + +Tue Jan 18 23:49:15 CET 2011 + +./batcher.sh -m 2 --all-types --self-communication ~/papers/iso/*.spdl + +Solved: do "watch -n 10 ./WIPER.sh 11" +(wiper.sh finds lsf files accessed longer ago than 11 minutes and wipes them) + +./test-mpa-alltypes.sh + + + +Mon Jan 24 14:55:23 CET 2011 + +./batcher.sh -m 2 --all-types Protocols/MultiProtocolAttacks/*.spdl + + + +Sat Jan 29 13:35:22 CET 2011 + +./batcher.sh -m 2 -A --self-communication Protocols/MultiProtocolAttacks/*.spdl diff --git a/Vagrant Files/files/scyther/ns3.spdl b/Vagrant Files/files/scyther/ns3.spdl new file mode 100644 index 0000000..edde4ab --- /dev/null +++ b/Vagrant Files/files/scyther/ns3.spdl @@ -0,0 +1,47 @@ +/* + * Needham-Schroeder protocol + */ + +// The protocol description + +protocol ns3(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {ni,I}pk(R) ); + recv_2(R,I, {ni,nr}pk(I) ); + claim(I,Running,R,ni,nr); + send_3(I,R, {nr}pk(R) ); + + claim(I,Secret,ni); + claim(I,Secret,nr); + claim(I,Alive); + claim(I,Weakagree); + claim(I,Commit,R,ni,nr); + claim(I,Niagree); + claim(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {ni,I}pk(R) ); + claim(R,Running,I,ni,nr); + send_2(R,I, {ni,nr}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim(R,Secret,ni); + claim(R,Secret,nr); + claim(R,Alive); + claim(R,Weakagree); + claim(R,Commit,I,ni,nr); + claim(R,Niagree); + claim(R,Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/nsl3-broken.spdl b/Vagrant Files/files/scyther/nsl3-broken.spdl new file mode 100644 index 0000000..3681cd9 --- /dev/null +++ b/Vagrant Files/files/scyther/nsl3-broken.spdl @@ -0,0 +1,40 @@ +/* + * Needham-Schroeder-Lowe protocol, + * broken version (wrong role name in first message) + */ + +// The protocol description + +protocol nsl3-broken(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {ni,R}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + send_3(I,R, {nr}pk(R) ); + + claim_i1(I,Secret,ni); + claim_i2(I,Secret,nr); + claim_i3(I,Niagree); + claim_i4(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {ni,R}pk(R) ); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim_r1(R,Secret,ni); + claim_r2(R,Secret,nr); + claim_r3(R,Niagree); + claim_r4(R,Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/nsl3.spdl b/Vagrant Files/files/scyther/nsl3.spdl new file mode 100644 index 0000000..c393e73 --- /dev/null +++ b/Vagrant Files/files/scyther/nsl3.spdl @@ -0,0 +1,47 @@ +/* + * Needham-Schroeder-Lowe protocol + */ + +// The protocol description + +protocol nsl3(I,R) +{ + role I + { + fresh ni: Nonce; + var nr: Nonce; + + send_1(I,R, {ni,I}pk(R) ); + recv_2(R,I, {ni,nr,R}pk(I) ); + claim(I,Running,R,ni,nr); + send_3(I,R, {nr}pk(R) ); + + claim(I,Secret,ni); + claim(I,Secret,nr); + claim(I,Alive); + claim(I,Weakagree); + claim(I,Commit,R,ni,nr); + claim(I,Niagree); + claim(I,Nisynch); + } + + role R + { + var ni: Nonce; + fresh nr: Nonce; + + recv_1(I,R, {ni,I}pk(R) ); + claim(R,Running,I,ni,nr); + send_2(R,I, {ni,nr,R}pk(I) ); + recv_3(I,R, {nr}pk(R) ); + + claim(R,Secret,ni); + claim(R,Secret,nr); + claim(R,Alive); + claim(R,Weakagree); + claim(R,Commit,I,ni,nr); + claim(R,Niagree); + claim(R,Nisynch); + } +} + diff --git a/Vagrant Files/files/scyther/precompute-ike.sh b/Vagrant Files/files/scyther/precompute-ike.sh new file mode 100644 index 0000000..7b7652f --- /dev/null +++ b/Vagrant Files/files/scyther/precompute-ike.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +./batcher.sh -m 2 --all-types --self-communication ~/src/ikev2/pp-results/mpa/ikev1*.spdl +./batcher.sh -m 2 --all-types --self-communication ~/src/ikev2/pp-results/mpa/ikev2*.spdl + diff --git a/Vagrant Files/files/scyther/progressbarDummy.py b/Vagrant Files/files/scyther/progressbarDummy.py new file mode 100644 index 0000000..9ddd7e9 --- /dev/null +++ b/Vagrant Files/files/scyther/progressbarDummy.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +""" + +Dummy. + +Author: Cas Cremers + +""" + +class ProgressBar(object): + + def __init__(self,widgets=[],maxval=100): + self.widgets = widgets + self.maxval = maxval + + def start(self): + if self.widgets: + if len(self.widgets) > 0: + print self.widgets[0], + + def update(self,count): + pass + + def finish(self): + print " Done." + + +def SimpleProgress(): + return + +def ETA(): + return + +def Percentage(): + return + +def Bar(marker,left,right): + return + +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/scyther-gui.py b/Vagrant Files/files/scyther/scyther-gui.py new file mode 100644 index 0000000..d20be43 --- /dev/null +++ b/Vagrant Files/files/scyther/scyther-gui.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +#--------------------------------------------------------------------------- +# Try to get wxPython +try: + import wx +except ImportError,err: + from Scyther import Misc + + errmsg = "Problem with importing the required [wxPython] package." + + if 'No module' in str(err): + errmsg = """Could not find the required [wxPython] package. +Please install this package in order to use the graphical user +interface of Scyther. +The [wxPython] packages can be found at http://www.wxpython.org/ + +Ubuntu users: the wxPython packages are called 'python-wxgtk' followed by the +version number.""" + elif ('32-bit mode' in str(err)) or ('no matching architecture' in str(err)): + import os + + key = "VERSIONER_PYTHON_PREFER_32_BIT" + data = "yes" + + keyfound = False + try: + if sys.environment[key] == data: + keyfound = True + except: + pass + + if keyfound: + """ + We already tried to set the environment variable, but it is still not working. + """ + import sys + #print "Key found. good job. no success." + + errmsg = """Problem with importing the required [wxPython] package. + + Possibly the problem is caused by wxPython only working in 32-bit mode currently. + You can try the following on the command line: + + $ export VERSIONER_PYTHON_PREFER_32_BIT=yes + $ ./scyther-gui.py""" + + else: + """ + Key not found. Try if that works. + """ + import sys + from subprocess import call + + #print "Key not found. Trying to set it now." + # TODO: check for MAC's if we need something like 'pythonw' + call(sys.argv, shell=True, env={key: data}) + sys.exit(0) + + + Misc.panic(""" +ERROR: + +%s + +Note that you can still use the Scyther binaries in the 'Scyther' directory. + +The exact error was: +-------------------------------------------------------------------------------- +%s +-------------------------------------------------------------------------------- + """ % (errmsg,err)) + + + +#--------------------------------------------------------------------------- +""" import externals """ +import sys +import os +from optparse import OptionParser, SUPPRESS_HELP +from subprocess import * + +#--------------------------------------------------------------------------- + +""" Import scyther-gui components """ +from Scyther import Scyther,Misc +from Gui import About,Preference,Mainwindow + +#--------------------------------------------------------------------------- + +def parseArgs(): + usage = "usage: %s [options] [inputfile]" % sys.argv[0] + description = "scyther-gui is a graphical user interface for the scyther protocol verification tool." + parser = OptionParser(usage=usage,description=description) + + # command + parser.add_option("-V","--verify",dest="command",default=None,action="store_const",const="verify", + help="Immediately verify the claims of the protocol (requires input file)") + parser.add_option("-s","--state-space",dest="command",default=None,action="store_const",const="statespace", + help="Immediately generate the complete characterization of the protocol (requires input file)") + parser.add_option("-a","--auto-claims",dest="command",default=None,action="store_const",const="autoverify", + help="Immediately verified protocol using default claims (requires input file)") + #parser.add_option("-c","--check",dest="command",default=None,action="store_const",const="check", + # help="Immediately check protocol (requires input file)") + + # License + parser.add_option("-l","--license",dest="license",default=False,action="store_const",const=True, + help="Show license") + + # no-splash + parser.add_option("-N","--no-splash",dest="splashscreen",default=True,action="store_const",const=False, + help="Do not show the splash screen") + + # misc debug etc (not shown in the --help output) + parser.add_option("","--test",dest="test",default=False,action="store_true", + help=SUPPRESS_HELP) + + return parser.parse_args() + +#--------------------------------------------------------------------------- + +class MySplashScreen(wx.SplashScreen): + def __init__(self,basedir): + path = os.path.join(basedir,"Images") + image = os.path.join(path,"scyther-splash.png") + bmp = wx.Image(image).ConvertToBitmap() + wx.SplashScreen.__init__(self, bmp, + wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT, + 5000, None, -1) + self.Bind(wx.EVT_CLOSE, self.OnClose) + self.fc = wx.FutureCall(2000, self.ShowMain) + + def OnClose(self, evt): + # Make sure the default handler runs too so this window gets + # destroyed + evt.Skip() + self.Hide() + + # if the timer is still running then go ahead and show the + # main frame now + if self.fc.IsRunning(): + self.fc.Stop() + self.ShowMain() + + + def ShowMain(self): + if self.fc.IsRunning(): + self.Raise() + + +#--------------------------------------------------------------------------- + +def isSplashNeeded(opts): + if not opts.command: + if opts.splashscreen and not (Preference.get('splashscreen') in ['false','off','disable','0']): + return True + return False + +#--------------------------------------------------------------------------- + +class ScytherApp(wx.App): + def OnInit(self): + import os, inspect + + wx.GetApp().SetAppName("Scyther-gui") + + # Determine base directory (taking symbolic links into account) + cmd_file = os.path.realpath(os.path.abspath(inspect.getfile( inspect.currentframe() ))) + basedir = os.path.split(cmd_file)[0] + + # Parse arguments + (opts,args) = parseArgs() + + # License option may abort here + if opts.license: + print Scyther.GetLicense() + sys.exit(0) + + # Load preferences file + Preference.init() + + #""" + #Create and show the splash screen. It will then create and show + #the main frame when it is time to do so. + # + #The splash screen is disabled for automatic commands, and also + #by a setting in the preferences file. + #""" + #if isSplashNeeded(opts): + # splash = MySplashScreen(basedir) + # splash.Show() + + self.mainWindow = Mainwindow.MainWindow(opts,args) + self.SetTopWindow(self.mainWindow) + self.mainWindow.Show() + + if isSplashNeeded(opts): + dlg = About.AboutScyther(self.mainWindow,basedir) + dlg.ShowModal() + dlg.Destroy() + + return True + + def OnExit(self): + """ Tear down """ + + +#--------------------------------------------------------------------------- + +def CheckRequirements(): + """ Check for any required programs """ + + """ We need 'dot', in the graphviz package """ + from Scyther import FindDot + + FindDot.findDot() # If Graphviz is not found, this function will call panic to complain. + +#--------------------------------------------------------------------------- + + +if __name__ == '__main__': + CheckRequirements() + scythergui = ScytherApp() + scythergui.MainLoop() + +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/scyther-gui.rc b/Vagrant Files/files/scyther/scyther-gui.rc new file mode 100644 index 0000000..cd3a913 --- /dev/null +++ b/Vagrant Files/files/scyther/scyther-gui.rc @@ -0,0 +1,4 @@ +wxicon icon Images/scyther-gui-64.ico +wxicon icon Images/scyther-gui-32.ico +wxicon icon Images/scyther-gui-16.ico +#include "wx/msw/wx.rc" diff --git a/Vagrant Files/files/scyther/scyther-manual.pdf b/Vagrant Files/files/scyther/scyther-manual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d35d7c3bb6da0afc2c2b6455db2070bfd28f3602 GIT binary patch literal 365769 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%0Aq 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�QbrJ0BOgu92GXGZt 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	sOMeNDri{`MJe4K8_;MZT@K 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 F0s!4`-Rl4V literal 0 HcmV?d00001 diff --git a/Vagrant Files/files/scyther/scyther.py b/Vagrant Files/files/scyther/scyther.py new file mode 100644 index 0000000..ef99d75 --- /dev/null +++ b/Vagrant Files/files/scyther/scyther.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +# +# python wrapper for the Scyther command-line tool +# + +#--------------------------------------------------------------------------- + +""" Import externals """ +import sys + +#--------------------------------------------------------------------------- + +""" Import scyther components """ +import Scyther.Scyther as Scyther + +#--------------------------------------------------------------------------- + +def usage(): + x = Scyther.Scyther() + x.xml = False + x.options = "--help" + x.verify() + return x + +def simpleRun(args): + x = Scyther.Scyther() + x.options = args + x.verify() + return x + +if __name__ == '__main__': + pars = sys.argv[1:] + if len(pars) == 0: + print usage() + else: + print simpleRun(" ".join(pars)) + + diff --git a/Vagrant Files/files/scyther/test-delta.py b/Vagrant Files/files/scyther/test-delta.py new file mode 100644 index 0000000..863d13b --- /dev/null +++ b/Vagrant Files/files/scyther/test-delta.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +""" + +Example script to show how to perform large-scale tests using the +Scyther Python API (contained in the Scyther subdirectory) + +In this example, we find the differences between two different switch +settings for a large set of protocols. + +The notification triggers if claim lists differ, or when a claim is okay +in one test but not in the other. Hence, we ignore differences between +complete/bounded verification. + +Author: Cas Cremers + + +Define the strings below. + +TEST0 is used for both, TEST1/2 define the difference between +the tests. +""" +#--------------------------------------------------------------------------- + +TEST0 = "" +TEST1 = "--max-runs=1" +TEST2 = "--max-runs=4" + +#--------------------------------------------------------------------------- + +""" Import externals """ +import commands + +#--------------------------------------------------------------------------- + +""" Import scyther components """ +from Scyther import Scyther + +#--------------------------------------------------------------------------- + +def filterProtocol(protocol): + """ + We may want to filter out some protocols. + This function allows that. Return True if it is okay (and should be + included) or False otherwise. + """ + include = True + return include + +def simpleRun(args): + x = Scyther.Scyther() + x.options = args + x.verify() + return x + +def ScytherRes(protocol,args=""): + """ + Run Scyther on a protocol and return a tuple with the + resulting object and claim list. + """ + global TEST0 + + args = "%s %s %s" % (TEST0, args, protocol) + s = simpleRun(args) + return (s,s.claims) + + +def findSameClaim(cl,claim): + """ + Find in claim list the claim that corresponds to claim + """ + for claim2 in cl: + if claim2.id == claim.id: + return claim2 + return None + + +def ScytherDiff(protocol): + """ + Check whether the two different switch settings yield a different + result. + """ + global TEST1, TEST2 + + (s1,cl1) = ScytherRes(protocol,TEST1) + (s2,cl2) = ScytherRes(protocol,TEST2) + + res = "" + if len(cl1) != len(cl2): + res += "Different claim lists:\n%s\n%s\n" % (cl1,cl2) + else: + for claim1 in cl1: + claim2 = findSameClaim(cl2,claim1) + if claim2 == None: + res += "%s not in second test.\n" % (claim1) + else: + if claim1.okay != claim2.okay: + res += "Different results:\n%s\n%s\n" % (claim1,claim2) + + if res == "": + return None + else: + return res + + +def findProtocols(): + """ + Find a list of protocol names + """ + + cmd = "find -iname '*.spdl'" + plist = commands.getoutput(cmd).splitlines() + nlist = [] + for prot in plist: + if filterProtocol(prot): + nlist.append(prot) + return nlist + + +def main(): + """ + Simple test case with a few protocols + """ + global TEST0,TEST1,TEST2 + + list = findProtocols() + print "Performing delta analysis" + print + print "String 0 (used for both): '%s'" % TEST0 + print "String 1: '%s'" % TEST1 + print "String 2: '%s'" % TEST2 + print + print "After filtering, we are left with the following protocols:", list + print + maxcount = len(list) + count = 1 + delta = 0 + for prot in list: + perc = (100 * count) / maxcount + print "[%i%%] %s: " % (perc,prot), + res = ScytherDiff(prot) + if res != None: + print + print "-" * 72 + print prot + print "-" * 72 + print res + delta = delta + 1 + else: + print "No interesting delta found." + count = count + 1 + + print + print "Analysis complete." + print "%i out of %i protocols differed [%i%%]." % (delta,maxcount,(100 * delta)/maxcount) + + +if __name__ == '__main__': + main() + + +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/test-mpa.py b/Vagrant Files/files/scyther/test-mpa.py new file mode 100644 index 0000000..bf5a344 --- /dev/null +++ b/Vagrant Files/files/scyther/test-mpa.py @@ -0,0 +1,896 @@ +#!/usr/bin/env python +""" + Scyther : An automatic verifier for security protocols. + Copyright (C) 2007-2013 Cas Cremers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + + +""" + +Example script to show how to perform large-scale tests using the +Scyther Python API (contained in the Scyther subdirectory) + +In this example, multi-protocol attack analysis is performed on a small +test set. + +Author: Cas Cremers + +""" + +from Scyther import Scyther + +from optparse import OptionParser, OptionGroup, SUPPRESS_HELP +import time +import os.path +import json + +try: + from progressbar import * + PROGRESSBAR = True +except ImportError: + from progressbarDummy import * + PROGRESSBAR = False + print """ +Missing the progressbar library. + +It can be downloaded from: + +http://code.google.com/p/python-progressbar/ + +""" + +FOUND = [] +ALLMPA = [] +ALLCLAIMS = [] +INVOLVED = [] +PROTFILETONAME = {} +PROTNAMETOFILE = {} +OPTS = None +ARGS = None +PICKLEDATA = set() + + +#--------------------------------------------------------------------------- + +def parseArgs(): + usage = "usage: %prog [options] [inputfile]" + description = "test-mpa.py is a test script to help with multi-protocol analysis." + parser = OptionParser(usage=usage,description=description, version="%prog 2.0") + + group = OptionGroup(parser, "Bounding the search space") + group.add_option("-m","--max-protocols",type="int",dest="maxprotocols",default=3, + help="Define maximum number of protocols in a multi-protocol attack [3].") + + group.add_option("-r","--max-runs",type="int",dest="maxruns",default=4, + help="Define maximum number of runs in the analysis [4].") + + group.add_option("-T","--timeout",type="int",dest="timeout",default=600, + help="Timeout in seconds for each analysis [600].") + + group.add_option("-L","--limit",type="int",dest="limit",default=0, + help="Limit the length of the list of protocols [None].") + parser.add_option_group(group) + + group = OptionGroup(parser, "Matching type options") + group.add_option("-t","--typed",dest="defoptarray",default=[],action="append_const",const="--match=0", + help="Verify protocols with respect to a typed model (-m 0) [default]") + group.add_option("-b","--basic-types",dest="defoptarray",default=[],action="append_const",const="--match=1", + help="Verify protocols with respect to basic type flaws only (-m 1)") + group.add_option("-u","--untyped",dest="defoptarray",default=[],action="append_const",const="--match=2", + help="Verify protocols with respect to an untyped model (-m 2)") + group.add_option("-A","--all-types",dest="alltypes",default=False,action="store_true", + help="Verify protocols with respect to all matching types") + parser.add_option_group(group) + + group = OptionGroup(parser, "Restricting self-communication") + group.add_option("-U","--init-unique",dest="defoptarray",default=[],action="append_const",const="--init-unique", + help="Use Scythers --init-unique switch to filter out initiators talking to themselves.") + group.add_option("-E","--extravert",dest="defoptarray",default=[],action="append_const",const="--extravert", + help="Use Scythers --extravert switch to filter out agents talking to themselves.") + group.add_option("","--self-communication",dest="selfcommunication",default=False,action="store_true", + help="Explore all self-communication restrictions (as MPA-only option).") + parser.add_option_group(group) + + # Misc + parser.add_option("","--pickle",dest="pickle", + help="Do not invoke Scyther but write intended calls to a file with the given name.") # action="store" and type="string" are defaults + parser.add_option("-l","--latex",dest="latex", + help="Output latex files with the given prefix.") # action="store" and type="string" are defaults + parser.add_option("-v","--verbose",dest="verbose",default=False,action="store_true", + help="Be more verbose.") + parser.add_option("-D","--debug",dest="debug",default=False,action="store_true", + help="Enable debugging features.") + parser.add_option("-p","--plain",dest="plain",default=False,action="store_true", + help="Ensure plain output, e.g., no progress bars.") + + return parser.parse_args() + +#--------------------------------------------------------------------------- + +class Attack(object): + + def __init__(self,claim,mpalist): + + self.claim = claim + self.mpalist = mpalist + + def protocol(self): + return self.claim.protocol + + def mpashort(self): + + s = [] + for fn in self.mpalist: + ptn = os.path.normpath(fn) + (head,tail) = os.path.split(ptn) + s.append(tail) + + return s + + def claimid(self): + return "%s" % (self.claim.id) + + def __str__(self): + s = "(%s,%s)" % (self.claim.id, self.mpashort()) + return s + + def fullstr(self): + s = "%s,%s" % (self.claim.id, self.mpalist) + return s + + def __cmp__(self,other): + s1 = self.fullstr() + s2 = other.fullstr() + if (s1 == s2): + return 0 + else: + if s1 < s2: + return -1 + else: + return 1 + + +#--------------------------------------------------------------------------- + + +def uniq(l): + + ll = [] + for x in l: + if x not in ll: + ll.append(x) + return ll + + +def powerset(s): + """ + s is a set + returns the powerset + """ + pws = set([frozenset()]) + for el in s: + # Double old powerset by adding its elements and also new ones + for s2 in pws.copy(): + if len(s2) == 0: + pws.add(frozenset([el])) + else: + pws.add(frozenset([el]).union(s2)) + return pws + + +#--------------------------------------------------------------------------- + +def MyScyther(protocollist,filt=None,options=[],checkpickle=True): + """ + Evaluate the composition of the protocols in protocollist. + If there is a filter, i.e. "ns3,I1" then only this specific claim + will be evaluated. + + By default, when Pickling, no evaluation is done (checkpickle=True). + Setting 'checkpickle' to False ignores this check and verifies anyway. + """ + global OPTS + global PICKLEDATA + + s = Scyther.Scyther() + + # Standard + opts = OPTS.defoptarray + options + + # Cover for caching issue where no --match= option is given (default to 0) + matchfound = False + for opt in opts: + if opt.startswith("--match="): + matchfound = True + break + if not matchfound: + opts.append("--match=0") + + # Adding other command-line parameters (i.e. with arguments) + opts.append("-T %i" % (int(OPTS.timeout))) + opts.append("--max-runs=%i" % (int(OPTS.maxruns))) + + # arguments to call + s.options = (" ".join(sorted(uniq(opts)))).strip() + if OPTS.debug: + print s.options + + for protocol in sorted(protocollist): + s.addFile(protocol) + if checkpickle and OPTS.pickle: + # Do not really verify! Just dump request if not already known + if s.verifyOne(filt, checkKnown=True) == False: + PICKLEDATA.add((tuple(sorted(protocollist)),s.options,filt)) + else: + # Verify results + s.verifyOne(filt) + return s + + +def getCorrectIsolatedClaims(protocolset,options=[]): + """ + Given a set of protocols, determine the correct claims when run in + isolation. + Returns a tuple, consisting of + - a list of compiling protocols + - a list of tuples (protocol,claimid) wich denote correct claims + """ + correctclaims = [] + goodprotocols = [] + + if not OPTS.plain: + widgets = ['Scanning for claims that are correct in isolation: ', SimpleProgress(), ' protocols (', Percentage(), ') ', + Bar(marker='#',left='[',right=']') + ] + pbar = ProgressBar(widgets=widgets, maxval=len(protocolset)) + pbar.start() + count = 0 + cpcount = 0 + for protocol in protocolset: + # verify protocol in isolation + s = MyScyther([protocol],options=options,checkpickle=False) + # investigate the results + goodprotocols.append(protocol) + allfalse = True + for claim in s.claims: + global ALLCLAIMS + global PROTFILETONAME + global PROTNAMETOFILE + + if claim not in ALLCLAIMS: + ALLCLAIMS.append(claim) + + if claim.okay: + correctclaims.append((protocol,claim.id)) + allfalse = False + + PROTFILETONAME[protocol] = str(claim.protocol) + PROTNAMETOFILE[str(claim.protocol)] = protocol + + count += 1 + if not allfalse: + cpcount += 1 + if not OPTS.plain: + pbar.update(count) + + if not OPTS.plain: + pbar.finish() + return (goodprotocols,correctclaims,cpcount) + + +def verifyProtList(protlist,claimid,options=[]): + """ + Check attacks on this protocol list. + Returns True if no attack ("correct") and False if an attack is found. + """ + s = MyScyther(protlist,claimid,options) + claim = s.getClaim(claimid) + if claim: + if not claim.okay: + return False + return True + + + +def verifyProtSubSet(protlist,claimid,options=[]): + """ + Check attacks on true subsets of this list. + Note subsets must include the claim id + """ + global OPTS + + ps = powerset(set(protlist)) + for s in ps: + if (len(s) > 0) and (len(s) < len(protlist)): + res = verifyProtList(list(s),claimid,options) + if res == False: + """ + If an attack is found we're actually done but for pickle we + make an exception to generate all possible variants. + """ + if not OPTS.pickle: + return False + return True + + +def verifyMPAattack(mpalist,claimid,options=[]): + """ + Check for Multi-Protocol Attacks on this protocol list. + Returns True if no attack ("correct") and False if an MPA attack is found. + + First consider subsets, so if there is an attack there, don't consider others. + """ + global OPTS + + res = verifyProtSubSet(mpalist,claimid,options) + if res or OPTS.pickle: + """ + Only really needed when no attack found but for pickle we make an + exception to generate all possible variants. + """ + return verifyProtList(mpalist,claimid,options) + return True + + +def verifyMPAlist(mpalist,claimid,options=[]): + """ + Check the existence of a multi-protocol attack in this context + + If an attack is found, we return False, otherwise True. This is + needed for the iteration later. + """ + global OPTS, ARGS + + if OPTS.debug: + print time.asctime(), mpalist, claimid, options + + if not verifyMPAattack(mpalist,claimid,options): + global FOUND + global ALLFOUND + global INVOLVED + + claim = claimidToClaim(claimid) + + # This is an MPA attack! + if OPTS.debug: + print "I've found a multi-protocol attack on claim %s in the context %s." % (claimid,str(mpalist)) + + att = Attack(claim,mpalist) + FOUND.append(att) + ALLFOUND.append(att) + + inv = [claim.protocol] + for fn in mpalist: + global PROTFILETONAME + inv.append(PROTFILETONAME[fn]) + + for pn in inv: + if pn not in INVOLVED: + INVOLVED.append(pn) + + #return False + + return True + + +def constructMPAlist(protocolset,claimid,mpalist,length,start,callback,options=[]): + """ + Append a list of parallel protocols, without duplicates, + such that the added part is lexicographically ordered (from + index 'start' in the protocol list) + For each possible list, the function callback is called. If the + callback returns true, iteration proceeds (returning true in the + end), otherwise it aborts and returns false. + """ + if len(mpalist) < length: + # list is not long enough yet + for pn in range(start,len(protocolset)): + p = protocolset[pn] + if p not in mpalist: + if not constructMPAlist(protocolset,claimid,mpalist + [p],length,pn+1,callback,options=options): + return False + return True + else: + # list is long enough: callback + return callback(mpalist,claimid,options) + + +def findMPA(protocolset,protocol,claimid,options=[]): + """ + The protocol claim is assumed to be correct. When does it break? + """ + global OPTS + + # First we examine 2-protocol attacks, and then increase the + # number of parallel protocols if we don't find any attacks on the + # claim. + maxcount = OPTS.maxprotocols + count = 2 + if len(protocolset) < maxcount: + # we cannot have more protocols in parallel than there are + # protocols. + maxcount = len(protocolset) + + # the actual incremental search loop + while count <= maxcount: + constructMPAlist(protocolset,claimid,[protocol],count,0,verifyMPAlist,options) + count += 1 + return None + + +def foundToDicts(attacklist = []): + """ + Turn a list of attacks into a more structured dict of dicts + protocolname -> claimid -> P(attack) + """ + res = {} + for att in attacklist: + pn = str(att.protocol()) + cl = att.claimid() + + if pn not in res.keys(): + res[pn] = {} + if cl not in res[pn].keys(): + res[pn][cl] = set() + res[pn][cl].add(att) + return res + + +def findAllMPA(protocolset,options=[],mpaoptions=[]): + """ + Given a set of protocols, find multi-protocol attacks + """ + + global FOUND + global OPTS, ARGS + global PROTNAMETOFILE + global ALLCLAIMS + + FOUND = [] + + # Find all correct claims in each protocol + (protocolset,correct,cpcount) = getCorrectIsolatedClaims(protocolset,options) + print "Investigating %i correct claims in %i protocols." % (len(correct), cpcount) + + mpaprots = [] + res = [] + + if len(correct) == 0: + print "Nothing to do." + return res + + if OPTS.verbose: + """ + When verbose, list correct claims in protocols + """ + pmapclaims = {} + for (protocol,claimid) in correct: + if protocol not in pmapclaims.keys(): + pmapclaims[protocol] = set() + pmapclaims[protocol].add(claimid) + print "Protocols with correct claims:" + if len(pmapclaims.keys()) == 0: + print " None." + else: + for pk in pmapclaims.keys(): + print " %s, %s" % (pk, pmapclaims[pk]) + print + left = set() + for p in protocolset: + if p not in pmapclaims.keys(): + left.add(p) + print "Protocols with no correct claims:" + if len(left) == 0: + print " None." + else: + for p in left: + print " %s" % (p) + print + + # output of all claims (only if latex required) + + if OPTS.latex: + clset = set() + for claim in ALLCLAIMS: + prot = str(claim.protocol) + file = PROTNAMETOFILE[prot] + clid = claim.id + descr = claim.roledescribe() + + tup = (file,prot,clid,descr) + clset.add(tup) + + fp = open("gen-%s-claims.txt" % (OPTS.latex),"w") + + fp.write("%% OPTS: %s\n" % OPTS) + fp.write("%% ARGS: %s\n" % ARGS) + + for (file,prot,clid,descr) in sorted(clset): + fp.write("%s; %s; %s; %s\n" % (file,prot,clid,descr)) + + fp.close() + + # Latex output of protocols with correct claims + if OPTS.latex: + pmapclaims = {} + for (protocol,claimid) in correct: + if protocol not in pmapclaims.keys(): + pmapclaims[protocol] = set() + pmapclaims[protocol].add(claimid) + + fp = open("gen-%s-correctclaims.tex" % (OPTS.latex),"w") + + fp.write("%% OPTS: %s\n" % OPTS) + fp.write("%% ARGS: %s\n" % ARGS) + + fp.write("\\begin{tabular}{ll}\n") + fp.write("Protocol & Claims \\\\\n") + for protocol in sorted(pmapclaims.keys()): + fp.write("%s & " % (PROTFILETONAME[protocol])) + claims = sorted(pmapclaims[protocol]) + latexcl = set() + for claimid in claims: + claim = claimidToClaim(claimid) + latexcl.add(claim.roledescribe()) + + fp.write("; ".join(sorted(latexcl))) + fp.write("\\\\\n") + fp.write("\\end{tabular}\n") + fp.close() + + # For all these claims... + if not OPTS.plain: + widgets = ['Scanning for MPA attacks: ', SimpleProgress(), ' claims (', Percentage(), ') ', + Bar(marker='#',left='[',right=']'), + ETA() + ] + pbar = ProgressBar(widgets=widgets, maxval=len(correct)) + pbar.start() + count = 0 + + # Concatenate options but add space iff needed + alloptions = options + mpaoptions + + for (protocol,claimid) in correct: + # Try to find multi-protocol attacks + findMPA(protocolset,protocol,claimid,options=alloptions) + count += 1 + if not OPTS.plain: + pbar.update(count) + if not OPTS.plain: + pbar.finish() + + """ + The below computation assumes protocol names are unique to files, but if + they are not, some other errors should have been reported by the Scyther + backend anyway (conflicting protocol definitions in MPA analysis). + """ + for att in FOUND: + pn = att.protocol() + if pn not in mpaprots: + mpaprots.append(pn) + res.append(att) + + """ + Latex table of attacks + + TODO : map file names to protocol names, write out claim details + + TODO : remove main protocol from list (it's: "MPA attacks when run in parallel with") + + TODO : Check whether current tests stop after finding *one* MPA attack or whether they find *all*. + + """ + if OPTS.latex and not OPTS.pickle: + fp = open("gen-%s-mpaattacks.tex" % (OPTS.latex),"w") + + fp.write("%% OPTS: %s\n" % OPTS) + fp.write("%% ARGS: %s\n" % ARGS) + + fp.write("\\begin{tabular}{lll}\n") + fp.write("Protocol & Claim & MPA attacks \\\\ \n") + + # Convert to more useful structure (maybe move one level up) + res = foundToDicts(FOUND) + + """ + Scan per protocol in mpaprots (maybe sorted?) + """ + for prot in sorted(res.keys()): + """ + List claim and then attack scenarios (to some max?) + """ + ltprot = prot + for claimid in sorted(res[prot].keys()): + + firstclaim = True + for att in sorted(res[prot][claimid]): + + if firstclaim: + + ltclaim = att.claim.roledescribe() + firstclaim = False + + attl = att.mpalist + ltattacks = [] + for attprot in attl: + if PROTFILETONAME[attprot] != att.claim.protocol: + ltattacks.append(PROTFILETONAME[attprot]) + + fp.write("%s & %s & %s \\\\ \n" % (ltprot,ltclaim,sorted(ltattacks))) + + # Erase for cleaner table + ltprot = "" + ltclaim = "" + + fp.write("\\end{tabular}\n") + fp.close() + + print "-" * 70 + print "Summary:" + print + print "We scanned %i protocols with options [%s]." % (len(protocolset),options) + print "We found %i correct claims." % (len(correct)) + print "We then scanned combinations of at most %i protocols with options [%s]." % (OPTS.maxprotocols,alloptions) + if OPTS.pickle: + print "However, just precomputing now, hence we are not drawing any conclusions." + else: + print "We found %i MPA attacks." % (len(FOUND)) + print "The attacks involve the claims of %i protocols." % (len(mpaprots)) + print "-" * 70 + print + + return res + + +def claimidToClaim(claimid): + """ + Return claim object given a claim id + """ + global ALLCLAIMS + + for claim in ALLCLAIMS: + if claim.id == claimid: + return claim + + + +def showDiff(reslist): + """ + Show difference between (opts,mpaopts,attacklist) tuples in list + """ + if len(reslist) == 0: + print "Comparison list is empty" + return + + (opt1,mpaopt1,al1) = reslist[0] + print "-" * 70 + print "Base case: attacks for \n [%s]:" % (opt1 + mpaopt1) + print + print len(al1) + for a in al1: + print "Base attack: %s" % (a) + + print "-" * 70 + print + + for i in range(0,len(reslist)-1): + (opt1,mpaopt1,al1) = reslist[i] + (opt2,mpaopt2,al2) = reslist[i+1] + + print "-" * 70 + print "Comparing the attacks for \n [%s] with\n [%s]:" % (opt1 + mpaopt1, opt2 + mpaopt2) + print + print len(al1), len(al2) + for a in al2: + if a not in al1: + print "Added attack: %s" % (a) + for a in al1: + if a not in al2: + print "Removed attack: %s" % (a) + + print "-" * 70 + print + + + + + + +def makeChoices(): + """ + Make choice grid. + Later options should (intuitively) give more attacks. + + [ MPAonly, (text,switch)* ] + """ + + global OPTS, ARGS + + choices = [] + + if OPTS.alltypes: + + choices.append([ False, \ + ("no type flaws",["--match=0"]), \ + ("basic type flaws",["--match=1"]), \ + ("all type flaws",["--match=2"]), \ + ]) + + if OPTS.selfcommunication: + + choices.append([ True, \ + ("Disallow A-A",["--extravert"]), \ + ("Allow responder A-A",["--init-unique"]), \ + ("Allow A-A",[]) \ + ]) + + return choices + + +def exploreTree( i, choices , l, options = [], mpaoptions = []): + """ + Each choice[x] is an array again: + + MPAonly, (txt,arg)* + """ + + if i >= len(choices): + return [(options,mpaoptions,findAllMPA(l, options = options, mpaoptions = mpaoptions))] + + mpaonly = choices[i][0] + cl = choices[i][1:] + + res = [] + for (txt,arg) in cl: + + print "For choice %i, selecting options %s" % (i,txt) + if mpaonly: + o1 = [] + o2 = arg + else: + o1 = arg + o2 = [] + res = res + exploreTree(i+1, choices, l, options = options + o1, mpaoptions = mpaoptions + o2) + + return res + + + +def fullScan(l, options = [], mpaoptions = []): + + global OPTS + global ALLFOUND + global ALLCLAIMS + global INVOLVED + global PROTNAMETOFILE + global PROTFILETONAME + + ALLFOUND = [] + ALLCLAIMS = [] + INVOLVED = [] + + if OPTS.limit > 0: + l = l[:OPTS.limit] + + choices = makeChoices() + if len(choices) == 0: + """ + No choices, just evaluate + """ + res = findAllMPA(l, options = options, mpaoptions = mpaoptions) + + else: + lres = exploreTree(0, choices, l, options = options, mpaoptions = mpaoptions) + if len(lres) > 1: + if not OPTS.pickle: + showDiff(lres) + + allprots = set() + attprots = set() + invprots = set() + for att in ALLFOUND: + attprots.add(str(att.protocol())) + for cl in ALLCLAIMS: + allprots.add(str(cl.protocol)) + for prot in INVOLVED: + invprots.add(str(prot)) + + if not OPTS.pickle: + print "The bottom line: we found %i protocols with multi-protocol attacks from a set of %i protocols." % (len(attprots),len(allprots)) + print + + print "Multi-protocol attacks were found on:" + for prot in sorted(list(allprots & attprots)): + print " %s" % (prot) + print + + print "No multi-protocol attacks were found on these protocols, but they caused MPA attacks:" + for prot in sorted(list((allprots - attprots) & invprots)): + print " %s" % (prot) + print + + print "These protocols were not involved in any MPA attacks:" + for prot in sorted(list((allprots - attprots) - invprots)): + print " %s\t[%s]" % (prot,PROTNAMETOFILE[prot]) + print + + + + +def bigTest(): + """ + Perform the tests as reported in the book. + """ + import os + + global OPTS, ARGS + + l = [] + nl = [] + + """ + Check for any given filenames + """ + if len(ARGS) == 0: + # No filenames given + testpath = "Protocols/MultiProtocolAttacks/" + fl = os.listdir(testpath) + for fn in fl: + if fn.endswith(".spdl"): + nl.append(fn) + + # Prepend again the path + l = [] + for fn in nl: + l.append(testpath+fn) + else: + for fn in ARGS: + l.append(fn) + nl = l + + # Report list + print "Performing multi-protocol analysis for the following protocols:", nl + + fullScan(l) + + + +def main(): + global OPTS, ARGS, PICKLEDATA + + (OPTS,ARGS) = parseArgs() + if OPTS.pickle: + PICKLEDATA = set() + + bigTest() + + #simpleTest() + + if OPTS.pickle: + pf = open(OPTS.pickle,"wa") + for el in PICKLEDATA: + json.dump(el,pf) + pf.write("\n") + pf.close() + + +if __name__ == '__main__': + main() + + +# vim: set ts=4 sw=4 et list lcs=tab\:>-: diff --git a/Vagrant Files/files/scyther/todo.txt b/Vagrant Files/files/scyther/todo.txt new file mode 100644 index 0000000..60e05af --- /dev/null +++ b/Vagrant Files/files/scyther/todo.txt @@ -0,0 +1,29 @@ +URGENT + +- + +TO BE DONE + +- Config file should use Python's confParse module. +- Save preferences in local file on close. + +WOULD LIKE TO HAVE + +- Font selector for graphs. +- Nice graph scaling for all platforms (now only supported under Linux + using the Python Imaging Library through postscript; currently + wxPython does not support any cross-platform vector format out of the + box, as SVG is still only a non-default build option.) +- Support for using an external editor. + - toggle for 'watch file'. + - toggle for 'auto-verify on change' or something like that. +- Ideally we somehow color the correct/incorrect tags in the editor. +- Line numbering is needed for the editor window otherwise you cannot + interpret attacks. Probably use wx.Py editor things. +- Scyther executable should be able to be set by means of preferences. + +IN AN IDEAL WORLD... + +- Use Python modules to generate the attack graphs from the XML, also + allow for eg. ASCII output. + diff --git a/Vagrant Files/files/scyther/wiper.sh b/Vagrant Files/files/scyther/wiper.sh new file mode 100644 index 0000000..11766f7 --- /dev/null +++ b/Vagrant Files/files/scyther/wiper.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# +# Wipe Brutus artefacts. +# +# Run as 'watch -n 10 ./wiper.sh' + +find lsf.* -maxdepth 0 -amin +11 -print -delete 2>&1 + + diff --git a/Vagrant Files/files/test folder/guide.txt b/Vagrant Files/files/test folder/guide.txt new file mode 100644 index 0000000..e740c7a --- /dev/null +++ b/Vagrant Files/files/test folder/guide.txt @@ -0,0 +1 @@ +These are where the scyther install instructions and user guide parts are going to go \ No newline at end of file diff --git a/Vagrant Files/scyther.sh b/Vagrant Files/scyther.sh new file mode 100644 index 0000000..b658516 --- /dev/null +++ b/Vagrant Files/scyther.sh @@ -0,0 +1,3 @@ +sudo apt-get update +sudo apt-get -y install graphviz python python-wxgtk3.0 +chmod +x /home/vagrant/Desktop/scyther/scyther/scyther-gui.py \ No newline at end of file -- GitLab