cpsa 2.4.0 → 2.5.0
raw patch · 108 files changed
+5324/−958 lines, 108 filesbinary-added
Files
- ChangeLog +96/−1
- NEWS +17/−0
- cpsa.cabal +39/−31
- doc/Makefile +10/−4
- doc/README +3/−2
- doc/bcasyntax.tex +41/−9
- doc/cpsa.bib +47/−1
- doc/cpsadesign.pdf binary
- doc/cpsadesign.tex +5/−1
- doc/cpsadiagrams.mp +84/−22
- doc/cpsagoals.pdf binary
- doc/cpsagoals.tex +718/−0
- doc/cpsaintroslides.pdf binary
- doc/cpsaoverview.pdf binary
- doc/cpsaprimer.pdf binary
- doc/cpsaprimer.tex +16/−0
- doc/cpsaspec.pdf binary
- doc/cpsaspec.tex +14/−11
- doc/cpsauser.html +60/−9
- doc/goals.scm +391/−0
- doc/index.html +37/−26
- doc/macros.tex +3/−1
- src/CPSA/Basic/Algebra.hs +77/−9
- src/CPSA/DiffieHellman/Algebra.hs +3/−0
- src/CPSA/Lib/Algebra.hs +14/−2
- src/CPSA/Lib/Characteristic.hs +248/−0
- src/CPSA/Lib/Goal.hs +113/−0
- src/CPSA/Lib/Loader.hs +313/−16
- src/CPSA/Lib/Protocol.hs +7/−6
- src/CPSA/Lib/Reduction.hs +13/−0
- src/CPSA/Lib/Strand.hs +223/−69
- src/CPSA/SAS/SAS.hs +29/−32
- src/cpsaextras/Main.scala +0/−47
- src/cpsaextras/Pretty.scala +0/−159
- src/cpsaextras/Printer.scala +0/−122
- src/cpsaextras/SExpr.scala +0/−282
- src/prover9.pl +10/−4
- src/scala/Main.scala +47/−0
- src/scala/Pretty.scala +159/−0
- src/scala/Printer.scala +122/−0
- src/scala/SExpr.scala +282/−0
- tst/DH_hack.tst +1/−1
- tst/blanchet.tst +1/−1
- tst/completeness-test.tst +1/−1
- tst/crushing.tst +1/−1
- tst/dass_simple.tst +1/−1
- tst/denning-sacco.tst +1/−1
- tst/deorig_contract.tst +1/−1
- tst/deorig_mesg.tst +1/−1
- tst/deorig_simple.tst +1/−1
- tst/dy.tst +1/−1
- tst/encsig.tst +1/−1
- tst/epmo-hash.tst +1/−1
- tst/epmo-key-hash.tst +1/−1
- tst/epmo.tst +1/−1
- tst/epmo_acctnum-key-hash.tst +1/−1
- tst/ffgg.tst +1/−1
- tst/fragile_pruning.tst +1/−1
- tst/goals.scm +355/−0
- tst/goals.tst +1117/−0
- tst/hashtest-key-hash.tst +1/−1
- tst/hashtest.tst +1/−1
- tst/incompleteness_example.tst +1/−1
- tst/isoreject.tst +1/−1
- tst/kelly1.tst +1/−1
- tst/kerberos.tst +1/−1
- tst/mass.tst +1/−1
- tst/mass2.tst +1/−1
- tst/missing_contraction.tst +1/−1
- tst/neuman-stubblebine-reauth.tst +1/−1
- tst/neuman-stubblebine.tst +1/−1
- tst/no_contraction.tst +1/−1
- tst/non_transforming.tst +1/−1
- tst/nonaug-prune.tst +1/−1
- tst/ns-l.tst +1/−1
- tst/ns.scm +9/−0
- tst/ns.tst +114/−32
- tst/nsl3.tst +1/−1
- tst/nsl4cm1.tst too large to diff
- tst/nslsk.tst +1/−1
- tst/or.tst +1/−1
- tst/pca.tst +1/−1
- tst/pen-non-orig-test.tst +1/−1
- tst/pkinit.tst +1/−1
- tst/preprocess.tst +1/−1
- tst/print.tst +1/−1
- tst/pruning1.tst +1/−1
- tst/sigenc.tst +1/−1
- tst/sorted_epmo_acctnum.tst +1/−1
- tst/targetterms2.tst +1/−1
- tst/targetterms6.tst +1/−1
- tst/targetterms8.tst +1/−1
- tst/timestamping.tst +1/−1
- tst/uncarried_keys.tst +1/−1
- tst/unilateral.scm +92/−0
- tst/unilateral.tst +336/−0
- tst/uo.tst +1/−1
- tst/wang-hash.tst +1/−1
- tst/wang-key-hash.tst +1/−1
- tst/weird.tst +1/−1
- tst/wide-mouth-frog-scyther.tst +1/−1
- tst/wide-mouth-frog.tst +1/−1
- tst/wonthull.tst +1/−1
- tst/wonthull2.tst +1/−1
- tst/wonthull3.tst +1/−1
- tst/woolam.tst +1/−1
- tst/yahalom-6.3.6.tst +1/−1
- tst/yahalom.tst +1/−1
ChangeLog view
@@ -1,3 +1,99 @@+2015-05-21 John D. Ramsdell <ramsdell@mitre.org>++ * cpsa.cabal (Version): Tagged as version 2.5.0++2015-04-27 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Lib/Loader.hs (ReturnFail): Added ReturnFail Monad so+ that fail is correctly handled. Added Functor and Applicative+ instance to support GHC 7.10 base library.++2015-04-20 John D. Ramsdell <ramsdell@mitre.org>++ * cpsa.cabal (Source-Repository): Added github source repository.++2015-04-10 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Lib/Strand.hs (mkListener): The role used for listener+ strands is now the one stored in the protocol. It has a single+ variable x of sort mesg as its set of variables. This change+ enables satisfaction checking on skeleton that include listeners.++2015-04-02 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Lib/Strand.hs (hull): Removed the hulling by+ deorigination mode and returned to the hulling by compression+ algorithm. Hulling is only used on the initial preskeleton.++ * src/CPSA/SAS/SAS.hs (form): Changed the output form from defsas+ to defgoal.++2015-03-30 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Lib/Loader.hs (loadPrimary): Improved the error+ messages for ill-formed atomic formulas.++ * src/CPSA/SAS/SAS.hs (loadPOV, loadOtherPreskel): Flushed the+ check that an atom assumed to uniquely originate must originate in+ a skeleton. In this case, cpsasas generates a uniq assertion+ rather than a uniq-at assertion.++2015-03-27 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Lib/Loader.hs (findGoal): Allow more than one sentence+ in a defgoal.++ * src/CPSA/SAS/SAS.hs (Preskel): Added pnon predicate symbol.++ * src/CPSA/Lib/Strand.hs (toSkeleton): Added hulling to the+ process of converting an input preskeleton into a skeleton.++2015-03-26 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Lib/{Characteristic,Strand,Loader}.hs: Added new+ toplevel form: defgoal. The characteristic skeleton of the+ antecedent in the goal is extracted and used as the initial+ skeleton.++2015-03-24 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Lib/{Reduction,Strand,Loader}.hs: Made it so that when+ a shape does not satisfy a goal, an environment showing why is+ printed. For each goal, the output is yes when the goal is+ satisfied or (no (VAR VAL)...).++2015-03-20 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Lib/{Goal,Strand,Loader}.hs: Added goal loading and+ satisfaction checking. When a shape satisfies all goals in a+ point-of-view skeleton, the shape is annotated with+ (satifies-all-goals).++2015-03-19 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/Basic/Algebra.hs (Term): Added node variables and+ constants for security goals.++ * src/CPSA/SAS/SAS.hs (form): Changed the format of a shape+ analysis sentences. Instead of a bare formula, the formula is+ wrapped in a defsas form, as in (defsas PROT SAS). Removed the+ protocol from role position predicates and parameter predicates.+ Replaced function symbols uniq and sprec with uniq-at and str-prec+ respectively.++2015-03-17 John D. Ramsdell <ramsdell@mitre.org>++ * src/CPSA/SAS/SAS.hs (displayEq): Use = for function symbol+ instead of equal.++2014-11-24 John D. Ramsdell <ramsdell@mitre.org>++ * src/prover9.pl: Added missing mesg predicates in output.++2014-11-17 John D. Ramsdell <ramsdell@mitre.org>++ * cpsa.cabal (Version): Tagged as version 2.4.0+ 2014-11-15 John D. Ramsdell <ramsdell@mitre.org> * src/CPSA/SAS/SAS.hs (nodeForm): Fixed bug where some role@@ -26,7 +122,6 @@ 2014-09-05 John D. Ramsdell <ramsdell@mitre.org> * cpsa.cabal (Version): Tagged as version 2.3.5- 2014-09-02 John D. Ramsdell <ramsdell@mitre.org>
NEWS view
@@ -1,5 +1,22 @@ CPSA NEWS -- history of user-visible changes. +* Changes in version 2.5.0++** Added support for security goals+ In CPSA, a security goal is expressed as a sentence in first-order+ logic. It asserts that if some properties hold for a skeleton,+ then some other properties must hold for all shapes computed by+ CPSA starting with the skeleton. Security goals can be used to+ formally state authentication and secrecy goals of a protocol.+ + Security goals have been integrated into the main CPSA program.+ The new defgoal form can be used to pose an analysis problem by a+ sentence instead of a skeleton. CPSA extracts a point-of-view+ skeleton from the antecedent of the formula and then analyzes it.+ When it prints a shape, it checks to see if the shape satisfies the+ conclusion of the security goal. See cpsagoals.pdf for more+ information.+ * Changes in version 2.4.0 ** Added program cpsasas
cpsa.cabal view
@@ -1,5 +1,5 @@ Name: cpsa-Version: 2.4.0+Version: 2.5.0 Maintainer: ramsdell@mitre.org Cabal-Version: >= 1.6 License: BSD3@@ -46,24 +46,25 @@ Build-Type: Simple Data-Files: index.html readme.html cpsauser.html cpsa.mk Make.hs cpsaprimer.pdf- cpsaoverview.pdf cpsaintroslides.pdf cpsaspec.pdf cpsadesign.pdf- ffgg.scm ns.scm blanchet.scm or.scm woolam.scm yahalom.scm+ cpsagoals.pdf cpsaoverview.pdf cpsaintroslides.pdf cpsaspec.pdf+ cpsadesign.pdf ffgg.scm ns.scm blanchet.scm or.scm woolam.scm+ yahalom.scm goals.scm Data-Dir: doc Extra-Source-Files: Makefile ChangeLog README NEWS ghci cpsatst setup.bat doc/README doc/Makefile doc/macros.tex doc/cpsaprimer.tex- doc/bcasyntax.tex doc/cpsaintroslides.tex doc/mitreslides.sty- doc/cpsaspec.tex doc/cpsadesign.tex doc/cpsaoverview.tex- doc/cpsadiagrams.mp doc/strands.mp doc/cmstrands.mp- doc/carriers.mp doc/termtree.mp doc/blanchet.mp doc/mitrelogo.mp- doc/cpsa.bib doc/SDAG.lhs+ doc/cpsagoals.tex doc/bcasyntax.tex doc/cpsaintroslides.tex+ doc/mitreslides.sty doc/cpsaspec.tex doc/cpsadesign.tex+ doc/cpsaoverview.tex doc/cpsadiagrams.mp doc/strands.mp+ doc/cmstrands.mp doc/carriers.mp doc/termtree.mp doc/blanchet.mp+ doc/mitrelogo.mp doc/cpsa.bib doc/SDAG.lhs src/index.html src/cpsacgi src/cpsacgi.py src/cpsajson.py src/split.py src/cpsa2svg src/cpsa.el src/httpd_allow_execmem.te src/cpsaperm.scm src/cpsaops.scm src/preskel src/cpsa.pl src/unsorted.pl src/pp.pl src/sexpr.pl src/perm.pl src/prover9.pl src/zoom.js src/js2hs- src/ghcmemlimit build.xml src/cpsaextras/Main.scala- src/cpsaextras/Pretty.scala src/cpsaextras/Printer.scala- src/cpsaextras/SExpr.scala+ src/ghcmemlimit build.xml src/scala/Main.scala+ src/scala/Pretty.scala src/scala/Printer.scala+ src/scala/SExpr.scala tst/README tst/Makefile tst/Make.hs tst/checktst tst/cpsagraphall tst/cpsashapesall tst/blanchet.scm tst/blanchet.tst tst/completeness-test.scm@@ -78,22 +79,23 @@ tst/epmo_acctnum.lisp tst/epmo-hash.scm tst/epmo-hash.tst tst/epmo-key-hash.scm tst/epmo-key-hash.tst tst/epmo.scm tst/epmo.tst tst/ffgg.scm tst/ffgg.tst tst/fragile_pruning.scm- tst/fragile_pruning.tst tst/hashtest-key-hash.scm- tst/hashtest-key-hash.tst tst/hashtest.scm tst/hashtest.tst- tst/incompleteness_example.scm tst/incompleteness_example.tst- tst/isoreject.scm tst/isoreject.tst tst/kelly1.scm tst/kelly1.tst- tst/kelly64.lisp tst/kerb5.lisp tst/kerberos.scm tst/kerberos.tst- tst/mass2.lsp tst/mass2.tst tst/mass.lsp tst/mass.tst- tst/missing_contraction.scm tst/missing_contraction.tst- tst/neuman-stubblebine-alt.lisp tst/neuman-stubblebine-reauth.lisp- tst/neuman-stubblebine-reauth.lsp tst/neuman-stubblebine-reauth.tst- tst/neuman-stubblebine.scm tst/neuman-stubblebine.tst- tst/no_contraction.scm tst/no_contraction.tst tst/nonaug-prune.scm- tst/nonaug-prune.tst tst/non_transforming.scm- tst/non_transforming.tst tst/nsl3.scm tst/nsl3.tst tst/nsl4cm1.lsp- tst/nsl4cm1.tst tst/nsl4.lisp tst/nsl4resp2.lisp tst/nsl5i.lisp- tst/nsl5.lisp tst/ns-l.scm tst/nslsk.scm tst/nslsk.tst tst/ns-l.tst- tst/ns.scm tst/ns.tst tst/or.scm tst/or.tst tst/pca.scm tst/pca.tst+ tst/fragile_pruning.tst tst/goals.scm tst/goals.tst+ tst/hashtest-key-hash.scm tst/hashtest-key-hash.tst tst/hashtest.scm+ tst/hashtest.tst tst/incompleteness_example.scm+ tst/incompleteness_example.tst tst/isoreject.scm tst/isoreject.tst+ tst/kelly1.scm tst/kelly1.tst tst/kelly64.lisp tst/kerb5.lisp+ tst/kerberos.scm tst/kerberos.tst tst/mass2.lsp tst/mass2.tst+ tst/mass.lsp tst/mass.tst tst/missing_contraction.scm+ tst/missing_contraction.tst tst/neuman-stubblebine-alt.lisp+ tst/neuman-stubblebine-reauth.lisp tst/neuman-stubblebine-reauth.lsp+ tst/neuman-stubblebine-reauth.tst tst/neuman-stubblebine.scm+ tst/neuman-stubblebine.tst tst/no_contraction.scm+ tst/no_contraction.tst tst/nonaug-prune.scm tst/nonaug-prune.tst+ tst/non_transforming.scm tst/non_transforming.tst tst/nsl3.scm+ tst/nsl3.tst tst/nsl4cm1.lsp tst/nsl4cm1.tst tst/nsl4.lisp+ tst/nsl4resp2.lisp tst/nsl5i.lisp tst/nsl5.lisp tst/ns-l.scm+ tst/nslsk.scm tst/nslsk.tst tst/ns-l.tst tst/ns.scm tst/ns.tst+ tst/or.scm tst/or.tst tst/pca.scm tst/pca.tst tst/pen-non-orig-test.scm tst/pen-non-orig-test.tst tst/pkinit.scm tst/pkinit.tst tst/preprocess.scm tst/preprocess.tst tst/print.scm tst/print.tst tst/pruning1.scm tst/pruning1.tst tst/sigenc.scm@@ -110,8 +112,13 @@ tst/wonthull2.scm tst/wonthull2.tst tst/wonthull3.scm tst/wonthull3.tst tst/wonthull.scm tst/wonthull.tst tst/woolam.scm tst/woolam.tst tst/yahalom-6.3.6.scm tst/yahalom-6.3.6.tst- tst/yahalom.scm tst/yahalom.tst+ tst/yahalom.scm tst/yahalom.tst tst/unilateral.scm+ tst/unilateral.tst +Source-Repository head+ Type: git+ Location: git://github.com/ramsdell/cpsa.git+ -- Algebra implementations must import CPSA.Lib.CPSA. -- Tools may additionally import CPSA.Lib.Entry. -- No other modules in CPSA.Lib should be imported by applications.@@ -125,9 +132,10 @@ Other-Modules: Paths_cpsa CPSA.Lib.Vector CPSA.Lib.Utilities CPSA.Lib.Pretty CPSA.Lib.SExpr CPSA.Lib.Printer CPSA.Lib.Notation CPSA.Lib.Entry- CPSA.Lib.Algebra CPSA.Lib.Protocol CPSA.Lib.Strand CPSA.Lib.Loader- CPSA.Lib.Displayer CPSA.Lib.Cohort CPSA.Lib.Expand CPSA.Lib.CPSA- CPSA.Lib.Reduction CPSA.Basic.Algebra CPSA.DiffieHellman.Algebra+ CPSA.Lib.Algebra CPSA.Lib.Protocol CPSA.Lib.Goal CPSA.Lib.Strand+ CPSA.Lib.Characteristic CPSA.Lib.Loader CPSA.Lib.Displayer+ CPSA.Lib.Cohort CPSA.Lib.Expand CPSA.Lib.CPSA CPSA.Lib.Reduction+ CPSA.Basic.Algebra CPSA.DiffieHellman.Algebra Executable cpsagraph Main-Is: CPSA/Graph/Main.hs
doc/Makefile view
@@ -10,6 +10,7 @@ SHELL = /bin/sh PRIMER = cpsaprimer+GOALS = cpsagoals OVERVIEW = cpsaoverview SLIDES = cpsaintroslides DESIGN = cpsadesign@@ -31,8 +32,8 @@ %.ind: %.idx makeindex $* -all: $(PRIMER).pdf $(OVERVIEW).pdf $(SLIDES).pdf \- $(DESIGN).pdf $(SPEC).pdf+all: $(PRIMER).pdf $(GOALS).pdf $(OVERVIEW).pdf \+ $(SLIDES).pdf $(DESIGN).pdf $(SPEC).pdf $(PRIMER).pdf: $(MP_SRCS:.mp=-0.mps) $(TEX_SRCS) \ $(PRIMER).tex $(PRIMER).bbl@@ -40,6 +41,11 @@ if test -f $(PRIMER).idx; then $(MAKE) $(PRIMER).ind; fi pdflatex $(PRIMER).tex +$(GOALS).pdf: $(MP_SRCS:.mp=-0.mps) $(TEX_SRCS) \+ $(GOALS).tex $(GOALS).bbl+ if test ! -f $(GOALS).aux; then pdflatex $(GOALS).tex; fi+ pdflatex $(GOALS).tex+ $(OVERVIEW).pdf: $(OVERVIEW).tex $(OVERVIEW).bbl if test ! -f $(OVERVIEW).aux; then pdflatex $(OVERVIEW).tex; fi pdflatex $(OVERVIEW).tex@@ -59,8 +65,8 @@ if test -f $(SPEC).idx; then $(MAKE) $(SPEC).ind; fi pdflatex $(SPEC).tex -CLEAN_FILES := $(PRIMER).pdf $(OVERVIEW).pdf $(SLIDES).pdf \- $(DESIGN).pdf $(SPEC).pdf \+CLEAN_FILES := $(PRIMER).pdf $(GOALS).pdf $(OVERVIEW).pdf \+ $(SLIDES).pdf $(DESIGN).pdf $(SPEC).pdf \ $(wildcard *.log *.aux *.toc *.mps *.mpx *.lot *.lof) \ $(wildcard *.bbl *.blg *.ind *.idx *.ilg *.out)
doc/README view
@@ -8,12 +8,13 @@ * cpsaoverview.pdf: Another attempt at a gentle introduction to CPSA +* cpsagoals.pdf: CPSA and Formal Security Goals, an introduction+ to reasoning about security goals using first-order logic.+ * cpsaspec.pdf: The CPSA Specification, a formal specification of the algorithm * cpsadesign.pdf: CPSA Design, a description of implementation choices--* cpsadha.pdf: Diffie-Hellman Algebra (an experiment with known flaws). To build the documentation, you need Metapost and XY-pic. On Linux, Metapost is supplied via the package texlive-metapost, and XY-pic is
doc/bcasyntax.tex view
@@ -1,14 +1,18 @@ The complete syntax for the analyzer using the Basic Crypto Algebra is-shown in Table~\ref{tab:syntax}. The start grammar symbol is-\textsc{file}, and the terminal grammar symbols are: \textsc{(, ),- symbol, string, integer,} and the constants set in typewriter font.+shown in Tables~\ref{tab:syntax} and~\ref{tab:goal}. The start+grammar symbol is \textsc{file}, and the terminal grammar symbols+are: \textsc{(, ), symbol, string, integer,} and the constants set in+typewriter font. The language used for stating security goals is in+Table~\ref{tab:goal}. The goal language adds the sort+symbol \texttt{node}. The \textsc{alist}, \textsc{prot-alist}, \textsc{role-alist},-and \textsc{skel-alist} productions are Lisp style association lists,-that is, lists of key-value pairs, where every key is a symbol.-Key-value pairs with unrecognized keys are ignored, and are available-for use by other tools. On output, unrecognized key-value pairs are-preserved when printing protocols, but elided when printing skeletons.+\textsc{skel-alist}, and \textsc{goal-alist} productions are+Lisp style association lists, that is, lists of key-value pairs, where+every key is a symbol. Key-value pairs with unrecognized keys are+ignored, and are available for use by other tools. On output,+unrecognized key-value pairs are preserved when printing protocols,+but elided when printing skeletons. \begin{table} \newcommand{\sym}[1]{\textup{\texttt{#1}}}@@ -19,7 +23,7 @@ (\sym{herald}~title~alist) \\title&$\leftarrow$&$\mbox{symbol}\mid\mbox{string}$ \\form&$\leftarrow$&-$\mbox{comment}\mid\mbox{protocol}\mid\mbox{skeleton}$+$\mbox{comment}\mid\mbox{protocol}\mid\mbox{skeleton}\mid\mbox{goal}$ \\ comment&$\leftarrow$& (\sym{comment}~\ldots) \\ protocol&$\leftarrow$&@@ -71,6 +75,34 @@ \end{tabular} \end{center} \caption{{\cpsa} Syntax}\label{tab:syntax}+\end{table}++\begin{table}+\newcommand{\sym}[1]{\textup{\texttt{#1}}}+\begin{center}\scshape+\begin{tabular}{rcl}+goal&$\leftarrow$&+(\sym{defgoal} id sentence+ goal-alist)+\\ sentence&$\leftarrow$&(\sym{forall} (decl$\ast$) implication)+\\ implication&$\leftarrow$&+(\sym{implies} \mbox{antecedent} \mbox{conclusion})+\\ conclusion&$\leftarrow$&(\sym{false})+ $\mid$ existential $\mid$ (\sym{or} existential$\ast)$+\\ existential&$\leftarrow$&(\sym{exists}+(decl$\ast$) antecedent) $\mid$ antecedent+\\ antecedent&$\leftarrow$& atomic $\mid$ (\sym{and} atomic$\ast$)+\\ atomic&$\leftarrow$&(\sym{p} roleid pos nvar)+\\ &$\mid$&(\sym{p} roleid param nvar term)+\\ &$\mid$&(\sym{str-prec} nvar nvar) $\mid$ (\sym{prec} nvar nvar)+\\ &$\mid$&(\sym{non} term) $\mid$ (\sym{pnon} term) $\mid$ (\sym{uniq} term)+\\ &$\mid$&(\sym{uniq-at} term nvar) $\mid$ (= term term)+\\ roleid&$\leftarrow$& string+\\ pos&$\leftarrow$& integer+\\ nvar&$\leftarrow$& id+\\ param&$\leftarrow$& string+\end{tabular}+\end{center}+\caption{{\cpsa} Syntax Continued}\label{tab:goal} \end{table} The contents of a file can be interpreted as a sequence of
doc/cpsa.bib view
@@ -223,6 +223,20 @@ OPTannote = {} } +@Manual{cpsagoals09,+ title = {{CPSA} and Formal Security Goals},+ OPTkey = {},+ author = {John D.~Ramsdell},+ organization = {The MITRE Corporation},+ OPTaddress = {},+ OPTedition = {},+ OPTmonth = {},+ year = 2015,+ note = {In \url{http://hackage.haskell.org/package/cpsa} source+ distribution, \texttt{doc} directory},+ OPTannote = {}+}+ @Manual{cpsaoverview09, title = {{CPSA} Overview}, OPTkey = {},@@ -399,10 +413,42 @@ author = {John D. Ramsdell and Joshua D. Guttman and Jonathan K. Millen and Brian O'Hanlon}, title = {An Analysis of the {CAVES} Attestation Protocol using {CPSA}},- note = {\url{http://arxiv.org/abs/1207.0418v1}},+ note = {\url{http://arxiv.org/abs/1207.0418}}, institution = {The {MITRE} Corporation}, month = dec, year = 2009, type = {{MITRE} Technical Report}, number = {{MTR090213}}+}++@InProceedings{GuttmanLiskovRowe14,+ author = {Joshua D. Guttman and Moses D. Liskov and Paul D. Rowe},+ title = {Security Goals and Evolving Standards},+ booktitle = {Security Standardization Research},+ year = 2014,+ editor = {Liqun Chen and Chris Mitchell},+ volume = 8839,+ series = {LNCS},+ pages = {93--110},+ month = dec,+ publisher = {Springer},+}++@Article{Guttman14,+ author = {Joshua D. Guttman},+ title = {Establishing and Preserving Protocol Security Goals},+ journal = {Journal of Computer Security},+ year = 2014,+ volume = 22,+ number = 2,+ pages = {201--267}}++@Unpublished{prover9,+ author = {Bill W. McCune},+ title = {Prover9},+ note = {\url{http://www.cs.unm.edu/~mccune/mace4/}},+ OPTkey = {},+ OPTmonth = {},+ OPTyear = {},+ OPTannote = {} }
doc/cpsadesign.pdf view
binary file changed (273796 → 275306 bytes)
doc/cpsadesign.tex view
@@ -927,8 +927,12 @@ Provides a common entry point for programs based on the CPSA library. \item[CPSA.Lib.Protocol:] Protocol data structures.+\item[CPSA.Lib.Goal:]+Security goal data structures. \item[CPSA.Lib.Strand:] Instance and preskeleton data structures and support functions.+\item[CPSA.Lib.Characteristic:]+Produces the characteristic skeleton of the antecedent of a goal. \item[CPSA.Lib.Cohort:] Computes the cohort associated with a skeleton or its generalization. \item[CPSA.Lib.Reduction:]@@ -936,7 +940,7 @@ \item[CPSA.Lib.Expand:] Expands macros using definitions in the input. \item[CPSA.Lib.Loader:]-Loads protocols and preskeletons from S-expressions.+Loads protocols, preskeletons, and goals from S-expressions. \item[CPSA.Lib.Displayer:] Displays protocols and preskeletons as S-expressions. \end{description}
doc/cpsadiagrams.mp view
@@ -73,11 +73,11 @@ strand.b(3, .5w, delta, btex $\mathstrut\mathit{resp}$ etex, node); % Messages and arrows- label.top(btex $\enc{N_1, A}{K_B}$ etex, .5[a1.e, b1.w]);+ label.top(btex $\enc{N_1, A}{K_B}$ etex, .5[a1.c, b1.c]); drawmsg(a1.e -- b1.w);- label.top(btex $\enc{N_1, N_2}{K_A}$ etex, .5[a2.e, b2.w]);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, .5[a2.c, b2.c]); drawmsg(b2.w -- a2.e);- label.top(btex $\enc{N_2}{K_B}$ etex, .5[a3.e, b3.w]);+ label.top(btex $\enc{N_2}{K_B}$ etex, .5[a3.c, b3.c]); drawmsg(a3.e -- b3.w); endfig; @@ -125,15 +125,15 @@ drawsucc(b1.s -- b2.n); drawsucc(b2.s -- b3.n); - label.top(btex $\enc{N_1, A}{K_P}$ etex, .5[a1.e, p1.w]);+ label.top(btex $\enc{N_1, A}{K_P}$ etex, .5[a1.c, p1.c]); drawmsg(a1.e -- p1.w);- label.top(btex $\enc{N_1, A}{K_B}$ etex, .5[p2.e, b1.w]);+ label.top(btex $\enc{N_1, A}{K_B}$ etex, .5[p2.c, b1.c]); drawmsg(p2.e -- b1.w);- label.top(btex $\enc{N_1, N_2}{K_A}$ etex, .75[b2.w, a2.e]);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, .75[b2.c, a2.c]); drawmsg(b2.w -- a2.e);- label.top(btex $\enc{N_2}{K_P}$ etex, .5[a3.e, p3.w]);+ label.top(btex $\enc{N_2}{K_P}$ etex, .5[a3.c, p3.c]); drawmsg(a3.e -- p3.w);- label.top(btex $\enc{N_2}{K_B}$ etex, .5[p4.e, b3.w]);+ label.top(btex $\enc{N_2}{K_B}$ etex, .5[p4.c, b3.c]); drawmsg(p4.e -- b3.w); endfig; @@ -156,17 +156,17 @@ endfor; % Messages and arrows- label.top(btex $\enc{N_1, A}{K_C}$ etex, alpha[a1.e, o1.w]);+ label.top(btex $\enc{N_1, A}{K_C}$ etex, alpha[a1.c, o1.c]); drawmsg(a1.e -- beta[a1.e,o1.w]); % Shortened arrow- label.top(btex $\enc{N_1, A}{K_B}$ etex, alpha[b1.w, o1.e]);+ label.top(btex $\enc{N_1, A}{K_B}$ etex, alpha[b1.c, o1.c]); drawmsg(beta[b1.w,o1.e] -- b1.w); % Shortened arrow- label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[a2.e, o2.w]);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[a2.c, o2.c]); drawmsg(o2.w -- a2.e);- label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[b2.w, o2.e]);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[b2.c, o2.c]); drawmsg(b2.w -- o2.e);- label.top(btex $\enc{N_2}{K_C}$ etex, alpha[a3.e, o3.w]);+ label.top(btex $\enc{N_2}{K_C}$ etex, alpha[a3.c, o3.c]); drawmsg(a3.e -- o3.w);- label.top(btex $\enc{N_2}{K_B}$ etex, alpha[b3.w, o3.e]);+ label.top(btex $\enc{N_2}{K_B}$ etex, alpha[b3.c, o3.c]); drawmsg(o3.e -- b3.w); endfig; @@ -186,17 +186,17 @@ endfor; % Messages and arrows- label.top(btex $\enc{N_1, A}{K_B}$ etex, alpha[a1.e, o1.w]);+ label.top(btex $\enc{N_1, A}{K_B}$ etex, alpha[a1.c, o1.c]); drawmsg(a1.e -- o1.w);- label.top(btex $\enc{N_1, A}{K_B}$ etex, alpha[b1.w, o1.e]);+ label.top(btex $\enc{N_1, A}{K_B}$ etex, alpha[b1.c, o1.c]); drawmsg(o1.e -- b1.w);- label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[a2.e, o2.w]);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[a2.c, o2.c]); drawmsg(o2.w -- a2.e);- label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[b2.w, o2.e]);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[b2.c, o2.c]); drawmsg(b2.w -- o2.e); label.top(btex $\enc{N_2}{K_B}$ etex,- alpha[a3.e, (xpart o2.w, ypart a3.c)]);- drawmsg(a3.e -- (beta * xpart o2.w, ypart a3.c));+ alpha[a3.c, (xpart o2.c, ypart a3.c)]);+ drawmsg(a3.c -- (beta * xpart o2.c, ypart a3.c)); endfig; % Incompleteness example@@ -233,10 +233,72 @@ strand.b(2, .5w, delta, btex $\mathstrut\mathit{resp}$ etex, node); % Messages and arrows- label.top(btex $\enc{N}{K}$ etex, .5[a1.e, b1.w]);+ label.top(btex $\enc{N}{K}$ etex, .5[a1.c, b1.c]); drawmsg(a1.e -- b1.w);- label.top(btex $N$ etex, .5[a2.e, b2.w]);+ label.top(btex $N$ etex, .5[a2.c, b2.c]); drawmsg(b2.w -- a2.e);+endfig;++beginfig(9);+ % Strand for principal A+ strand.a(3, origin, delta, btex $\mathstrut\mathit{init}$ etex, node);++ % Strand for principal B+ strand.b(2, w + a2.c, delta, btex $\mathstrut\mathit{resp}$ etex, node);++ % Centered ordering symbols+ boxit.o1(btex $\prec$ etex); o1.c = .5[a1.c, b1.c];+ boxit.o2(btex $\succ$ etex); o2.c = .5[a2.c, b2.c];++ for i = 1 upto 2:+ draw pic o[i];+ endfor;++ % Messages and arrows+ label.top(btex $\enc{N_1, A}{K_B}$ etex, alpha[a1.c, o1.c]);+ drawmsg(a1.e -- o1.w);+ label.top(btex $\enc{N_1, A}{K_B}$ etex, alpha[b1.c, o1.c]);+ drawmsg(o1.e -- b1.w);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[a2.c, o2.c]);+ drawmsg(o2.w -- a2.e);+ label.top(btex $\enc{N_1, N_2'}{K_A}$ etex, alpha[b2.c, o2.c]);+ drawmsg(b2.w -- o2.e);+ label.top(btex $\enc{N_2}{K_B}$ etex,+ alpha[a3.c, (xpart o2.c, ypart a3.c)]);+ drawmsg(a3.e -- (beta * xpart o2.w, ypart a3.c));+endfig;++beginfig(10);+ % Strand for principal A+ strand.a(3, origin, delta, btex $\mathstrut\mathit{resp}$ etex, node);++ % Strand for principal B+ strand.b(3, w, delta, btex $\mathstrut\mathit{init}$ etex, node);++ % Centered ordering symbols+ boxit.o2(btex $\prec$ etex); o2.c = .5[a2.c, b2.c];+ boxit.o3(btex $\succ$ etex); o3.c = .5[a3.c, b3.c];++ for i = 2 upto 3:+ draw pic o[i];+ endfor;++ % Messages and arrows+ label.top(btex $\enc{N_1, A}{K_B}$ etex,+ alpha[a1.c, (xpart o2.c, ypart a1.c)]);+ drawmsg(a1.e -- (beta * xpart o2.w, ypart a1.c));+ label.top(btex $\enc{N_1, A}{K_{B'}}$ etex,+ alpha[b1.c, (xpart o2.c, ypart b1.c)]);+ drawmsg((1-beta)[(xpart o2.e, ypart b1.c), b1.w] -- b1.w);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[a2.c, o2.c]);+ drawmsg(a2.e -- o2.w);+ label.top(btex $\enc{N_1, N_2}{K_A}$ etex, alpha[b2.c, o2.c]);+ drawmsg(o2.e -- b2.w);+ label.top(btex $\enc{N_2}{K_B}$ etex, alpha[a3.c, o3.c]);+ drawmsg(o3.w -- a3.e);+ label.top(btex $\enc{N_2}{K_{B'}}$ etex, alpha[b3.c, o3.c]);+ drawmsg(b3.w -- o3.e);+ endfig; verbatimtex
+ doc/cpsagoals.pdf view
binary file changed (absent → 194012 bytes)
+ doc/cpsagoals.tex view
@@ -0,0 +1,718 @@+\documentclass[12pt]{article}+\usepackage{amssymb}+\usepackage{amsmath}+\usepackage{url}+\usepackage{graphicx}+\usepackage{alltt}+\input{macros}++\newcommand{\sym}[1]{\textup{\texttt{#1}}}++\title{CPSA and Formal Security Goals}+\author{John D.~Ramsdell\\+ The MITRE Corporation\\ CPSA Version \version}++\begin{document}+\maketitle+\cpsacopying++\tableofcontents++\newpage++\listoffigures++\listoftables++\newpage++\section{Introduction}++\begin{sloppypar}+Analyzing a cryptographic protocol means finding out what security+properties---essentially, authentication and secrecy properties---are+true in all its possible executions.+\end{sloppypar}++Given a protocol definition and some assumptions about executions,+{\cpsa} attempts to produce descriptions of all possible executions of+the protocol compatible with the assumptions. Naturally, there are+infinitely many possible executions of a useful protocol, since+different participants can run it with varying parameters, and the+participants can run it repeatedly.++However, for many naturally occurring protocols, there are only+finitely many of these runs that are essentially different. Indeed,+there are frequently very few, often just one or two, even in cases+where the protocol is flawed. We call these essentially different+executions the \emph{shapes} of the protocol. Authentication and+secrecy properties are easy to ``read off'' from the shapes, as are+attacks and anomalies, according to the introduction in the {\cpsa}+Primer~\cite{cpsaprimer09}.++But how easy is it to read off authentication and secrecy properties?+What precisely is it that an expert sees? This paper describes+{\cpsa}'s support for reasoning about security goals using first-order+logic. With security goals expressed in first-order logic, intuition+is replaced by determining if a formula is true in all executions of+the protocol.++% \emph{Something about the benefits of first-order logic goes here.}++This treatment of security goals relies heavily on a branch of+first-order logic called model theory. It deals with the relationship+between descriptions in first-order languages and the structures that+satisfy these descriptions. In our case, the structures are skeletons+that denote a collection of executions of a protocol. This paper+attempts to describe the language of security goals and its+structures without requiring the reader to have studied model theory.++The model theoretical foundation of this approach to security goals+appears in~\cite{Guttman14}. A practical use of security goals in+protocol standardization is described in~\cite{GuttmanLiskovRowe14}.+The precise semantics of the goal language is+in~\cite[Appendix~C]{cpsaspec09}. The syntax of security goals+appears in~\cite[Table~2]{cpsaprimer09}.++The distribution in which this paper is included contains the sample+input {\cpsa} file \texttt{goals.scm}. It contains the examples in+this paper. You are encouraged to run the examples and examine the+output while reading this paper.++%% Use a margin width of 62 for S-expressions++\begin{figure}+\begin{center}+\includegraphics{cpsadiagrams-0.mps}\hfil+\includegraphics{cpsadiagrams-1.mps}\\+\end{center}+\begin{center}+\begin{minipage}{3in}+\begin{verbatim}+(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace+ (send (enc n1 a (pubk b)))+ (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace+ (recv (enc n1 a (pubk b)))+ (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))))+\end{verbatim}+\end{minipage}+\end{center}+\caption{Needham-Schroeder Initiator and Responder Roles}+\label{fig:ns roles}+\end{figure}++\begin{figure}+\begin{verbatim}+(defgoal ns ; Goal+ (forall ((b name) (n1 text) (z0 node))+ (implies+ (and (p "init" 2 z0)+ (p "init" "n1" z0 n1) (p "init" "b" z0 b)+ (non (privk b)) (uniq n1))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "b" z1 b))))))++(defskeleton ns ; Point of view skeleton+ (vars (a b name) (n1 n2 text))+ (defstrand init 3 (a a) (b b) (n1 n1) (n2 n2))+ (non-orig (privk b))+ (uniq-orig n1))+\end{verbatim}+\begin{center}+\includegraphics{cpsadiagrams-9.mps}+\end{center}+\begin{verbatim}+(defskeleton ns ; Shape+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n2 n2-0) (n1 n1) (b b) (a a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk b))+ (uniq-orig n1)+ (satisfied yes))+\end{verbatim}+\caption{Needham-Schroeder Initiator Point of View}+\label{fig:ns init}+\end{figure}++The {\cpsa} Primer~\cite{cpsaprimer09} is a prerequisite for reading+this paper. In particular, the Needham-Schroeder Protocol in+Section~10 is reanalyzed using security goals here. The roles are+displayed in Figure~\ref{fig:ns roles}.++The protocol is analyzed from the point of view of a complete run of+one instance of the initiator role. The input security goal, followed+by the point of view skeleton it generates and the shape produced by+{\cpsa}, are shown in Figure~\ref{fig:ns init}. The syntax and+semantics of the goal will be explained later. Roughly speaking, it+asserts that if a realized skeleton contains a full length initiator+strand, its private key is uncompromised, and it uniquely generates+\texttt{n1}, then the skeleton will contain a responder strand that+agrees with the initiator on the name \texttt{b}. The shape produced+by {\cpsa} contains the annotation \texttt{(satisfies yes)}. This+indicates that its structure satisfies the description given by the+security goal. It will be explained later why the properties of+{\cpsa} allows us to conclude that this goal is true in all executions+of the protocol, and therefore conclude that the Needham-Schroeder+protocol achieves this authentication goal.++\section{Syntax}\label{sec:syntax}++To be precise, a security goal is an order-sorted first-order logic+sentence in a restricted form. The sentence in Figure~\ref{fig:ns+ init} has the form shared by all security goals. It is a universally+quantified implication. The antecedent is a conjunction of atomic+formulas. For this sentence, the conclusion is an existentially+quantified conjunction of atomic formulas, but in general, the+conclusion is a disjunction of existentially quantified conjunctions+of atomic formulas. \sym{(false)} is a synonym for \sym{(or)}.++\begin{center}\scshape+ \begin{tabular}{rcl}+ goal&$\leftarrow$&(\sym{defgoal} prot sent$+$ comments)+ \\ sent&$\leftarrow$&(\sym{forall} (decl$\ast$) (\sym{implies} antec concl))+ \\ concl&$\leftarrow$&(\sym{false})+ $\mid$ existl $\mid$ (\sym{or} existl$\ast)$+ \\ existl&$\leftarrow$&(\sym{exists}+ (decl$\ast$) antec) $\mid$ antec+ \\ antec&$\leftarrow$&atomic $\mid$ (\sym{and} atomic$\ast$)+ \end{tabular}+\end{center}++Variables are declared as they are for roles and skeletons with one+exception, there is a new sort symbol \sym{node}. Notice that in the+sentence, variables \sym{z0} and \sym{z1} have sort \sym{node}. Every+universally quantified variable must occur in the antecedent of the+implication.++The predicates used to construct an atomic formula (\textsc{atomic})+are listed in Table~\ref{tab:predicates}. The first line gives the+syntax of a role position predicate. It contains three tokens,+\texttt{p}, a string that names a role, and an integer that specifies+a position within the trace of the role. That is, for role~$r$ with a+trace of length~$n$, there are~$n$ role position predicates,+\mbox{\texttt{p} $r$ $i$}, for $0\leq i < n$. The second line gives+the syntax of a role parameter predicate. It contains three tokens,+\texttt{p}, a string that names a role, and a string that names a role+variable. For role~$r$, there is role parameter predicate for each+variable declared by~$r$.++The empty string names the listener role of a protocol. The role+has the variable \texttt{x} of sort \texttt{mesg} as its only role+variable. There are two positions in the listener role.++When a variable of sort \sym{node} occurs in a formula, its position+must be specified using a role position formula. When an algebra+variable occurs in formula, its association with the parameter of some+role must be specified using a role parameter formula.++\begin{table}+\begin{center}+ \begin{tabular}{lcl}+ Symbol & Sort & Description\\+ \hline+ \scshape\sym{p} role pos & \dom{node} & \mbox{Role position} \\+ \scshape\sym{p} role param & $\dom{node}\times\dom{mesg}$+ & \mbox{Role parameter} \\+ \sym{str-prec}& $\dom{node}\times\dom{node}$+ & \mbox{Precedes on strand} \\+ \sym{prec}& $\dom{node}\times\dom{node}$+ & \mbox{Precedes} \\+ \sym{non}& \dom{atom}+ & \mbox{Non-origination} \\+ \sym{pnon}& \dom{atom}+ & \mbox{Penetrator non-origination} \\+ \sym{uniq}& \dom{atom}+ & \mbox{Unique origination} \\+ \sym{uniq-at}& $\dom{atom}\times\dom{node}$+ & \mbox{Unique origination at node} \\+ $=$ & $\dom{all}\times\dom{all}$ & Equality+ \end{tabular}+\end{center}+\caption{Predicates}\label{tab:predicates}+\end{table}++\section{Semantics}\label{sec:semantics}++In a \texttt{defgoal} sentence, the antecedent specifies the point of+view skeleton. We focus on the antecedent. In the example,++\begin{quote}+\begin{verbatim}+(defstrand init 3 (a a) (b b) (n1 n1) (n2 n2))+\end{verbatim}+\end{quote}+is extracted from+\begin{quote}+\begin{verbatim}+(and (p "init" 2 z0)+ (p "init" "n1" z0 n1) (p "init" "b" z0 b)).+\end{verbatim}+\end{quote}+Notice that {\cpsa} adds a binding for \texttt{a} and \texttt{n2} just+as it does had+\begin{quote}+\begin{verbatim}+(defstrand init 3 (b b) (n1 n1))+\end{verbatim}+\end{quote}+been given as input.++Our aim now is to specify how to decide if a security goal is true in+all possible executions of a protocol. A skeleton defines a set of+executions that contain the skeleton's structure. We say a skeleton+\emph{satisfies} a formula if the formula is true in all executions+that contain the skeleton's structure. To decide if a skeleton+satisfies a formula, we decide if it satisfies each of its atomic+formulas, and combine the results using the rules of first-order+logic.++Atomic formula \texttt{(p "init" 2 z0)} is called a role position+formula. A skeleton~$k$ satisfies the formula if \texttt{z0} maps to+a node $n=(s,2)$ in~$k$ such that+\begin{enumerate}+\item the trace of strand~$s$ in~$k$ has a length greater than 2, and+\item the trace when truncated to length 3 is an instance of the init+ role.+\end{enumerate}+Consider the shape in Figure~\ref{fig:ns init}. It satisfies+\texttt{(p "init" 2 z0)} when \texttt{z0} maps to $(0,2)$.++Atomic formula \texttt{(p "init" "n1" z0 n1)} is called a role+parameter formula. A skeleton~$k$ satisfies the formula if+\texttt{z0} maps to a node $n=(s,i)$ in~$k$ and \texttt{n1} maps to a+message algebra term~$t$ in~$k$ such that+\begin{enumerate}+\item the trace of strand~$s$ in~$k$ has a length greater than~$i$,+\item the trace truncated to length $i+1$ is an instance of the+ init role, and+\item the truncated trace is compatible with mapping the init role's+ \texttt{"n1"} role variable to~$t$.+\end{enumerate}+The shape in Figure~\ref{fig:ns init} satisfies \texttt{(p "init" "n1"+ z0 n1)} when \texttt{z0} maps to $(0,2)$ and \texttt{n1} maps to the+message algebra term \texttt{n1}.++Collectively, a skeleton satisfies the formula+\begin{quote}+\begin{verbatim}+(and (p "init" 2 z0)+ (p "init" "a" z0 a) (p "init" "b" z0 b)+ (p "init" "n1" z0 n1) (p "init" "n2" z0 n2))+\end{verbatim}+\end{quote}+if the skeleton contains the structure specified by+\begin{quote}+\begin{verbatim}+(defstrand init 3 (a a) (b b) (n1 n1) (n2 n2)).+\end{verbatim}+\end{quote}++The antecedent in Figure~\ref{fig:ns init} contains two origination+assertions. The formula \texttt{(non (privk b))} is extracted as+\texttt{(privk b)}. A skeleton~$k$ satisfies the formula if+\texttt{b} maps to a message algebra term~$t$ in~$k$ such that~$k$+assumes that~$t$ is non-originating. The unique origination formula for+\texttt{n1} is similarly extracted.++Putting it all together, the mapping+\[\{\mathtt{n1}\mapsto\mathtt{n1},+\mathtt{n2}\mapsto\mathtt{n2}, \mathtt{a}\mapsto\mathtt{a},+\mathtt{b}\mapsto\mathtt{b},\mbox{\tt z0}\mapsto(0,2)\}\] shows that+the shape in Figure~\ref{fig:ns init} satisfies the antecedent of the+security goal.++The \texttt{prec} predicate is used to assert a node precedes another+node. The conclusion in Figure~\ref{fig:ns init} with \texttt{(prec+ z1 z0)} added is satisfied by the shape using the mapping $\mbox{\tt+ z0}\mapsto(0,2)$ and $\mbox{\tt z1}\mapsto(1,1)$.++The \texttt{str-prec} predicate is used to assert a node precedes another+node and that both are on the same strand.++The \texttt{uniq-at} predicate is used to assert not only that an atom+uniquely originates, but also the node at which it originates. It is+typically used in conjunction with a \texttt{str-prec} formula. In+the Figure~\ref{fig:ns init} goal, the \texttt{(uniq n1)} formula+could have been replaced by+\begin{quote}+\begin{verbatim}+(p "init" 0 z2) (str-prec z2 z0) (uniq-at n1 z2),+\end{verbatim}+\end{quote}+where \texttt{z2} has sort \texttt{node}. The extracted point of view+skeleton is the same. Of course, an error is raised if the role+position formula is replaced by \texttt{(p "init" 1 z2)}.++Recall that our aim in analyzing a protocol is to find out what+security goals are true in all of its possible executions. We are+interested in runs of {\cpsa} that show that when every shape+satisfies a goal, it is true in every execution.++When {\cpsa} performs a shape analysis, every shape it generates+refines the input skeleton. Skeleton refinement is defined+in~\cite[Section~6]{cpsaprimer09}, but roughly speaking, skeleton~$A$+refines skeleton~$B$ if~$A$ contains the structure of skeleton~$B$.++The skeleton~$k_0$ extracted from the antecedent of a security goal+has the property that every skeleton than refines~$k_0$ satisfies the+antecedent. A skeleton with this property is called the+\emph{characteristic skeleton} of the antecedent.++Given a goal~\(\Phi\), consider a shape analysis starting from the+characteristic skeleton~$k_0$ of its antecedent. Assume {\cpsa} finds+shapes $k_1,\ldots,k_n$ and that {\cpsa} determines that each~$k_i$+satisfies~$\Phi$. Consider the executions that contain the structure+in~$k_0$. {\cpsa} tells us that each execution is in the executions+that contain the structure of some~$k_i$. Furthermore, because~$k_0$+is a characteristic skeleton, each~$k_i$ satisfies the antecedent+of~$\Phi$. Therefore,~$\Phi$ is true in all executions of the+protocol and maximally informative.++\section{Examples}\label{sec:examples}++This section contains examples of both authentication and secrecy+goals. The first example shows the feedback the user receives when a+shape does not satisfy a security goal. The second example shows how+to use a listener to state a secrecy goal.++\subsection{Needham-Schroeder Responder}\label{sec:ns resp}++\begin{figure}+\begin{verbatim}+(defgoal ns ; Goal+ (forall ((a b name) (n2 text) (z0 node))+ (implies+ (and (p "resp" 2 z0) (p "resp" "n2" z0 n2)+ (p "resp" "a" z0 a) (p "resp" "b" z0 b)+ (non (privk a)) (uniq n2))+ (exists ((z1 node))+ (and (p "init" 1 z1) (p "init" "b" z1 b)))))++(defskeleton ns ; Point of view skeleton+ (vars (a b name) (n1 n2 text))+ (defstrand init 3 (a a) (b b) (n1 n1) (n2 n2))+ (non-orig (privk a))+ (uniq-orig n2))+\end{verbatim}+\begin{center}+\includegraphics{cpsadiagrams-10.mps}+\end{center}+\begin{verbatim}+(defskeleton ns ; Shape+ (vars (n1 n2 text) (a b b-0 name))+ (defstrand resp 3 (n2 n2) (n1 n1) (b b) (a a))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b-0))+ (precedes ((0 1) (1 1)) ((1 2) (0 2)))+ (non-orig (privk a))+ (uniq-orig n2)+ (satisfies (no (a a) (b b) (n2 n2) (z0 (0 2))))+\end{verbatim}+\caption{Needham-Schroeder Responder Point of View}+\label{fig:ns resp}+\end{figure}++Figure~\ref{fig:ns resp} contains an analysis of Needham-Schroeder+from the point of view of a complete run of the responder under the+assumption that the responder's private key is uncompromised and the+nonce it generates uniquely originates.++The conclusion of the goal asserts that in an execution compatible+with the point of view, there must be an initiator strand that agrees+with the responder strand on the name \texttt{b}. The shape produced+by {\cpsa} is a counterexample to this assertion. Because of this,+{\cpsa} annotates the shape with+\begin{quote}+\begin{verbatim}+(satisfies (no (a a) (b b) (n2 n2) (z0 (0 2))).+\end{verbatim}+\end{quote}+The annotation includes a variable mapping for the shape that+satisfies the antecedent of the goal but does not satisfy its+conclusion. The mapping \texttt{(b b)} is the reason the shape does+not satisfy the goal.++Galvin Lowe identified this authentication failure in+Needham-Schroeder and provided a fix. In the Needham-Schroeder-Lowe+Protocol, the name \texttt{b} is included within the encryption in second+message of both roles. With this modification, the shape found by+{\cpsa} satisfies the security goal in Figure~\ref{fig:ns resp}, so+Needham-Schroeder-Lowe achieves this authentication goal.++\subsection{A Needham-Schroeder Secrecy Goal}\label{sec:secrecy goal}++\begin{figure}+\begin{quote}+\begin{verbatim}+(defgoal ns+ (forall ((a b name) (n1 text) (z0 z1 node))+ (implies+ (and (p "init" 2 z0) (p "init" "n1" z0 n1)+ (p "init" "a" z0 a) (p "init" "b" z0 b)+ (p "" 0 z1) (p "" "x" z1 n1) ; Listener+ (non (privk a)) (non (privk b)) (uniq n1))+ (false))))+\end{verbatim}+\end{quote}+\caption{Needham-Schroeder Secrecy Goal}\label{fig:ns secrecy}+\end{figure}++Figure~\ref{fig:ns secrecy} contains an analysis of Needham-Schroeder+from the point of view of a complete run of the initiator under the+assumption that the responder's and its peer's private key are+uncompromised and the nonce~\texttt{n1} it generates uniquely+originates. Futhermore, the point of view asserts that the nonce is+leaked using a listener.+\begin{quote}+\begin{verbatim}+(p "" 0 z1) (p "" "x" z1 n1) ; Listener+\end{verbatim}+\end{quote}++{\cpsa} finds no shapes, so Needham-Schroeder achieves this secrecy+goal and does not leak~\texttt{n1}.++\subsection{Unilateral Authentication}\label{sec:unilateral}++This example focuses on unilateral authentication. To best visualize+this example, process the sample file \texttt{goal.scm} with {\cpsa}+and display its output in a browser.++The protocol and its goal is shown in Figure~\ref{fig:unilateral}.+The goal asserts that if a realized skeleton contains a full length+initiator strand that uniquely generates \texttt{n1}, and+peer~\texttt{a}'s private key is uncompromised, then the skeleton will+contain a responder strand that agrees with the initiator on the+name~\texttt{a}. When given as input, {\cpsa} verifies that the goal+is true in all executions of the protocol.++\begin{figure}+\begin{minipage}{2.7in}+\begin{verbatim}+(defprotocol unilateral basic+ (defrole init+ (vars (a name) (n text))+ (trace+ (send (enc n (pubk a)))+ (recv n)))+ (defrole resp+ (vars (a name) (n text))+ (trace+ (recv (enc n (pubk a)))+ (send n))))+\end{verbatim}+\end{minipage}\hfil+\begin{minipage}{3.0in}+\begin{verbatim}+(defgoal unilateral+ (forall ((a name) (n text)+ (z0 node))+ (implies+ (and (p "init" 1 z0)+ (p "init" "n" z0 n)+ (p "init" "a" z0 a)+ (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1)+ (p "resp" "a" z1 a))))))+\end{verbatim}+\end{minipage}+\caption{Unilateral Protocol and Authentication Goal}\label{fig:unilateral}+\end{figure}++\begin{figure}+\begin{quote}+\begin{verbatim}+(defgoal ns+ (forall ((a name) (n text) (z0 node))+ (implies+ (and (p "init" 1 z0) (p "init" "n1" z0 n)+ (p "init" "b" z0 a) (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "b" z1 a))))))+\end{verbatim}+\end{quote}+\caption{Translated Unilateral Goal for the+ Initiator}\label{fig:unilateral ns init}+\end{figure}++\begin{figure}+\begin{quote}+\begin{verbatim}+(defgoal ns+ (forall ((a name) (n text) (z0 node))+ (implies+ (and (p "resp" 2 z0) (p "resp" "n2" z0 n)+ (p "resp" "a" z0 a) (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "init" 2 z1) (p "init" "a" z1 a)))))+\end{verbatim}+\end{quote}+\caption{Translated Unilateral Goal for the+ Responder}\label{fig:unilateral ns resp}+\end{figure}++In Section~\ref{sec:ns resp}, a goal written for the Needham-Schroeder+Protocol was reused to analyze the Needham-Schroeder-Lowe Protocol.+We now use the unilateral authentication goal to analyze+Needham-Schroeder.++Consider the goal in Figure~\ref{fig:unilateral ns init}. This goal+is the result of translating the Unilateral role position and+parameter predicates as follows.+\begin{center}+\begin{tabular}{l@{$\quad\rightarrow\quad$}l}+ \texttt{p "init" "n"}&\texttt{p "init" "n1"}\\+ \texttt{p "init" "a"}&\texttt{p "init" "b"}\\+ \texttt{p "resp" "a"}&\texttt{p "resp" "b"}+\end{tabular}+\end{center}+When given Figure~\ref{fig:unilateral ns init} as input, {\cpsa}+verifies that the goal is true in all executions of the protocol.++There is another way to translate the Unilateral goal.+\begin{center}+\begin{tabular}{l@{$\quad\rightarrow\quad$}l}+ \texttt{p "init" 1}&\texttt{p "resp" "2"}\\+ \texttt{p "init" "n"}&\texttt{p "resp" "n2"}\\+ \texttt{p "init" "a"}&\texttt{p "resp" "a"}\\+ \texttt{p "resp" "1"}&\texttt{p "init" "2"}\\+ \texttt{p "resp" "a"}&\texttt{p "init" "a"}+\end{tabular}+\end{center}+When given Figure~\ref{fig:unilateral ns resp} as input, {\cpsa}+verifies that the goal is true in all executions of the protocol.++{\cpsa} has demonstrated two ways in which Needham-Schroeder achieves+the goals of the Unilateral Protocol.++\section{The Whole Story}\label{sec:whole story}++The examples in the previous section demonstrate the typical way+security goals are analyzed with {\cpsa}. However, there are more+features that may be useful.++A \texttt{defgoal} form may contain more than one sentence. See+Figure~\ref{fig:ns init goals} for an example. When presented with+more than one sentence, {\cpsa} extracts the point of view skeleton+from the first sentence.++It is wise to ensure that the antecedent in every sentence is+identical. When {\cpsa} performs satisfaction-checking on+sentence~$\Phi$, it only determines if each shape it finds is+satisfied. If the point of view skeleton in not the characteristic+skeleton of the antecedent of~$\Phi$, the fact that all skeletons+satisfy~$\Phi$ cannot be used to conclude that~$\Phi$ is true in all+executions of the protocol.++\begin{figure}+\begin{quote}+\begin{verbatim}+(defgoal ns+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and (p "init" 1 z0) (p "init" "n1" z0 n)+ (p "init" "a" z0 a) (p "init" "b" z0 b)+ (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "b" z1 b)))))+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and (p "init" 1 z0) (p "init" "n1" z0 n)+ (p "init" "a" z0 a) (p "init" "b" z0 b)+ (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "a" z1 a))))))+\end{verbatim}+\end{quote}+\caption{Two Initiator Authentication Goals}\label{fig:ns init goals}+\end{figure}++{\cpsa} performs satisfaction-checking when an input skeleton in annotated+with one or more security goals. The annotation uses the+\texttt{goals} key.++\begin{quote}+ \begin{alltt}+(defskeleton+ \ldots+ (goals \textsc{sent\ensuremath{+}}))+ \end{alltt}+\end{quote}++The program \texttt{cpsasas}, discussed in the next section, can be+used to generate an formula with an antecedent such that the input+skeleton is the characteristic skeleton of the antecedent.++\subsection{Shape Analysis Sentences}\label{sec:sas}++A shape analysis sentence expresses all that can be learned from a run+of {\cpsa} as a security goal. If a security goal can be derived from+a shape analysis sentence, then the protocol achieves the security+goal, that is, the goal is true in all executions of the protocol.++The program \texttt{cpsasas} extracts shape analysis sentences from+the output of {\cpsa}. Consider the first example in this paper+(Figure~\ref{fig:ns init}), which is in the sample file+\texttt{goals.scm}. To generate a maximally informative security goal+from the initiator point of view with \texttt{ghci} and+\texttt{Make.hs}, type+\begin{quote}+\begin{verbatim}+$ ghci Make.hs+*Make> sas "goals"+\end{verbatim}+\end{quote}+When using GNU make, type ``\texttt{make goals\_sas.text}''. The+resulting shape analysis sentence is displayed in Figure~\ref{fig:ns+ sas}.++\begin{figure}+\begin{verbatim}+(defgoal ns+ (forall ((n1 n2 text) (b a name) (z z-0 node))+ (implies+ (and (p "init" 0 z) (p "init" 2 z-0)+ (p "init" "n1" z-0 n1) (p "init" "n2" z-0 n2)+ (p "init" "a" z-0 a) (p "init" "b" z-0 b)+ (str-prec z z-0) (non (privk b)) (uniq-at n1 z))+ (exists ((n2-0 text) (z-1 z-2 z-3 node))+ (and (p "init" 1 z-1) (p "resp" 0 z-2)+ (p "resp" 1 z-3) (p "resp" "n2" z-3 n2-0)+ (p "resp" "n1" z-3 n1) (p "resp" "b" z-3 b)+ (p "resp" "a" z-3 a) (prec z z-2) (prec z-3 z-1)+ (str-prec z z-1) (str-prec z-1 z-0)+ (str-prec z-2 z-3))))))+\end{verbatim}+\caption{Initiator Shape Analysis Sentence}\label{fig:ns sas}+\end{figure}++A shape analysis sentences asserts that either a realized skeleton+does not satisfy its antecedent or it satisfies one or more of the+disjuncts in its conclusion. {\cpsa} has been designed so that this+assertion is true. Therefore, every shape analysis sentence is true+in all executions.++A security goal is true in all executions if it can be derived from a+shape analysis sentence~\cite{Ramsdell12}. {\cpsa} comes with a+Prolog program that translates shape analysis sentences into Prover9+syntax~\cite{prover9}. Prover9 can then be used to perform the+required theorem-proving.++In practice, theorem-proving using shape analysis sentences is rarely+employed. It's clumsy and it requires too much expertise. The main+use of \texttt{cpsasas} is for generating a formula that is edited to+become a desired security goal.++\bibliography{cpsa}+\bibliographystyle{plain}++\end{document}
doc/cpsaintroslides.pdf view
binary file changed (93145 → 93099 bytes)
doc/cpsaoverview.pdf view
binary file changed (129002 → 128944 bytes)
doc/cpsaprimer.pdf view
binary file changed (273720 → 276659 bytes)
doc/cpsaprimer.tex view
@@ -1098,6 +1098,22 @@ (comment "Nothing left to do") \end{verbatim} +\section{First-Order Logic and Security Goals}\label{sec:security goals}++Another way to specify a problem statement is with a security goal. A+security goal a sentence in first-order logic. It asserts that if+some properties hold for a skeleton, then some other properties must+hold for all shapes computed by CPSA starting with the skeleton.+Security goals can be used to formally state authentication and+secrecy goals of a protocol.++The \texttt{defgoal} form is used to pose an analysis problem with a+sentence instead of a skeleton. CPSA extracts a point of view+skeleton from the antecedent of the formula and then analyzes it.+When it prints a shape, it checks to see if the shape satisfies the+conclusion of the security goal. See~\cite{cpsagoals09} for details.+The grammar of security goals is in Table~\ref{tab:goal}.+ \section{Macros}\label{sec:macros} After reading the input, {\cpsa} expands macros before in analyzing
doc/cpsaspec.pdf view
binary file changed (387594 → 387770 bytes)
doc/cpsaspec.tex view
@@ -2114,10 +2114,10 @@ each role~$\role_Y(C,N,U)\in P$ and variable~$x:S$ that occurs in~$C$, there is a protocol specific binary parameter predicate $P[r,x]:\dom{node}\times{}S$. The protocol independent unary-predicates are $\mathsf{non}: B$ for each base sort~$B$. The-remaining protocol independent predicates are binary, and are-$\mathsf{uniq}: B\times\dom{node}$,-$\mathsf{sprec}:\dom{node}\times\dom{node}$,+predicates are $\mathsf{non}: B$ and $\mathsf{uniq}: B$ for each base+sort~$B$. The remaining protocol independent predicates are binary,+and are $\mathsf{\uniqat}: B\times\dom{node}$,+$\mathsf{\strprec}:\dom{node}\times\dom{node}$, $\mathsf{prec}:\dom{node}\times\dom{node}$, and equality. Soon we define~$\form(k)=(Y,\Phi)$, where~$\Phi$ is $k$'s skeleton@@ -2158,12 +2158,14 @@ $P[r,x](v(s,h-1),t)$, where $r^c=C$ when $r=\role(C,N,U)$. \item For each $(s,i),(s,i')\in N$ such that $i<i'$, assert- $\cn{sprec}(v(s,i),v(s,i'))$.+ $\cn{\strprec}(v(s,i),v(s,i'))$. \item For each $(s,i)\prec^-(s',i')$ such that $s\neq s'$, assert $\cn{prec}(v(s,i),v(s',i'))$. \item For each $t\in N$, assert $\cn{non}(t)$. \item For each $t\in U$ and node~$n$ such that- $n\in\orig_k(t)$, assert $\cn{uniq}(t,v(n))$.+ $n\in\orig_k(t)$, assert $\cn{\uniqat}(t,v(n))$.+\item For each $t\in U$ without a point of origination in~$k$, assert+ $\cn{uniq}(t)$. \end{itemize} Given a set of homomorphisms $\delta_i\colon k_0\mapsto k_i$, its shape@@ -2212,8 +2214,8 @@ \qquad\quad\wedge\init_0(n_3)\wedge\init_a(n_3,a_1)\wedge \init_b(n_3,b_2)\wedge \init_s(n_3,s_1)\\-\qquad\quad\wedge\cn{uniq}(s_1,n_2)\wedge-\cn{prec}(n_3,n_2)\wedge\cn{sprec}(n_2,n_1)\\+\qquad\quad\wedge\cn{\uniqat}(s_1,n_2)\wedge+\cn{prec}(n_3,n_2)\wedge\cn{\strprec}(n_2,n_1)\\ \qquad\quad\wedge\cn{non}(a_1^{-1})\wedge \cn{non}(b_1^{-1}))) \end{array}$$@@ -2255,10 +2257,11 @@ \begin{itemize} \item $k,\alpha\models\cn{prec}(y,z)$ iff $\alpha(y)\prec\alpha(z)$.-\item $k,\alpha\models\cn{sprec}(y,z)$ iff $\alpha(y)\prec\alpha(z)$,+\item $k,\alpha\models\cn{\strprec}(y,z)$ iff $\alpha(y)\prec\alpha(z)$, $\alpha(y)=(s,i)$, and $\alpha(z)=(s,i')$. \item $k,\alpha\models\cn{non}(t)$ iff $\bar\alpha(t)\in\nu$.-\item $k,\alpha\models\cn{uniq}(t,y)$ iff $\bar\alpha(t)\in\upsilon$ and+\item $k,\alpha\models\cn{uniq}(t)$ iff $\bar\alpha(t)\in\upsilon$.+\item $k,\alpha\models\cn{\uniqat}(t,y)$ iff $\bar\alpha(t)\in\upsilon$ and $\alpha(y)\in\orig_k(\bar\alpha(t))$. \item $k,\alpha\models y=z$ iff $\bar\alpha(y)=\bar\alpha(z)$. \end{itemize}@@ -2273,7 +2276,7 @@ \[\cn{prec}(x,y) \land\cn{prec}(y,z)\supset \cn{prec}(x,z).\]-Furthermore, $\cn{sprec}(x,y)\supset\cn{prec}(x,y)$.+Furthermore, $\cn{\strprec}(x,y)\supset\cn{prec}(x,y)$. \bibliography{cpsa} \bibliographystyle{plain}
doc/cpsauser.html view
@@ -3,7 +3,7 @@ <head> <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" />- <title>CPSA 2.4 User Guide</title>+ <title>CPSA 2.5 User Guide</title> <meta name="generator" content="Amaya 9.54, see http://www.w3.org/Amaya/" /> <style type="text/css"> h1 { text-align: center }@@ -12,7 +12,7 @@ </head> <body>-<h1>CPSA 2.4 User Guide</h1>+<h1>CPSA 2.5 User Guide</h1> <p>The Cryptographic Protocol Shapes Analyzer (CPSA) attempts to enumerate all essentially different executions possible for a cryptographic protocol. We call@@ -59,11 +59,13 @@ <a href="#cpsajson"><code>cpsajson</code></a> program translates JSON encoded CPSA into CPSA S-Expressions.</p> -<p>The input syntax is essentially the same as the output syntax. A Lisp aware-editor will pretty print input, and the output is pretty printed. We use Emacs'-Scheme mode to prepare input. This document describes the syntax, but provides-little assistance for its interpretation. See the CPSA Tutorial document for-this information.</p>+<p>The input syntax is essentially the same as the output syntax. A+ Lisp aware editor will pretty print input, and the output is pretty+ printed. We use Emacs' Scheme mode to prepare input. This document+ describes the syntax, but provides little assistance for its+ interpretation. See the <a href="cpsaprimer.pdf">CPSA Primer</a> and+ <a href="cpsagoals.pdf">CPSA and Formal Security Goals</a> for more+ information.</p> <p>The typical pattern of usage is to enter the set of problems to be analyzed into a file, in this example, <code>prob.scm</code>, analyze the problems, and if@@ -131,9 +133,13 @@ protocol definitions and problem statements. A <a href="#usage">herald form</a> allows options normally specified on the command line to be specified within an input file. A problem-statement describes the initial behavior as a skeleton. The grammar-for a protocol follows.</p>+statement describes the initial behavior as a skeleton or a security+goal.</p> +<h3>Protocols</h3>++<p>The grammar for a protocol follows.</p>+ <blockquote> <pre>PROTOCOL ::= (defprotocol ID ALG ROLE+ PROT-ALIST) ID ::= SYMBOL@@ -190,6 +196,8 @@ other than <code>mesg</code>, or it if formed from one of the following operations: <code>pubk</code>, <code>privk</code>, <code>invk</code>, and <code>ltk</code>.</p> +<h3>Skeletons</h3>+ <blockquote> <pre>SKELETON ::= (defskeleton ID VARS STRAND+ SKEL-ALIST) STRAND ::= (defstrand ID INT MAPLET*) | (deflistener TERM)@@ -280,6 +288,49 @@ <code>(exp (exp h x) y) = (exp h (mul x y)</code>.</p> -->++<h3>First-order Logic and Security Goals</h3>++<p>Another way to specify a problem statement is with a security+ goal. A security goal a sentence in first-order logic. It asserts+ that if some properties hold for a skeleton, then some other+ properties must hold for all shapes computed by CPSA starting with+ the skeleton. Security goals can be used to formally state+ authentication and secrecy goals of a protocol.</p>++<p>The <code>defgoal</code> form is used to pose an analysis problem+ with a sentence instead of a skeleton. CPSA extracts a point of view+ skeleton from the antecedent of the formula and then analyzes it.+ When it prints a shape, it checks to see if the shape satisfies the+ conclusion of the security goal. See+ <a href="cpsagoals.pdf">CPSA and Formal Security Goals</a> for+ details.</p>++<p>To be precise, a security goal is an order-sorted first-order logic+ sentence in a restricted form. The set of sort symbols available+ for use in a <code>DECL</code> is the ones provided by the message+ algebra augmented with the symbol <code>node</code>. The form of a+ sentence is restricted by the syntax that follows.</p>++<blockquote>+ <pre>GOAL ::= (defgoal ID SENTENCE+ GOAL-ALIST)+SENTENCE ::= (forall (DECL*) (implies ANTECEDENT CONCLUSION))+CONCLUSION ::= (false) | EXISTENTIAL | (or EXISTENTIAL*)+EXISTENTIAL ::= (exists (DECL*) ANTECEDENT) | ANTECEDENT+ANTECEDENT ::= ATOMIC | (and ATOMIC*)+ATOMIC ::= (p ROLEID POS NVAR) | (p ROLEID PARAM NVAR TERM)+ | (str-prec NVAR NVAR) | (prec NVAR NVAR)+ | (non TERM) | (pnon TERM) | (uniq TERM)+ | (uniq-at TERM NVAR) | (= TERM TERM)+ROLEID ::= STRING+POS ::= INT+NVAR ::= ID+PARAM ::= STRING</pre>+</blockquote>++<p>The empty string names the listener role of a protocol. The+ role has the variable <code>x</code> of sort <code>mesg</code>+ as its only role variable. There are two positions in the listener role.</p> <h3>Macros and Includes</h3>
+ doc/goals.scm view
@@ -0,0 +1,391 @@+(herald goals)++;;; Section 1 --- Examples from CPSA and Formal Security Goals++;;; Needham-Schroeder from Section 10 of the CPSA Primer++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace+ (send (enc n1 a (pubk b)))+ (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace+ (recv (enc n1 a (pubk b)))+ (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder with no role origination assumptions"))++(defgoal ns+ (forall ((b name) (n1 text) (z0 node))+ (implies+ (and (p "init" 2 z0)+ (p "init" "n1" z0 n1) (p "init" "b" z0 b)+ (non (privk b)) (uniq n1))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "b" z1 b)))))+ (comment "Initiator point of view")+ (comment "Authentication goal: agreement on name b"))++(defgoal ns+ (forall ((b name) (n1 text) (z0 node))+ (implies+ (and (p "init" 2 z0)+ (p "init" "n1" z0 n1) (p "init" "b" z0 b)+ (non (privk b)) (uniq n1))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "b" z1 b)+ (prec z1 z0)))))+ (comment "Prec example"))++(defgoal ns+ (forall ((a b name) (n2 text) (z0 node))+ (implies+ (and (p "resp" 2 z0) (p "resp" "n2" z0 n2)+ (p "resp" "a" z0 a) (p "resp" "b" z0 b)+ (non (privk a)) (uniq n2))+ (exists ((z1 node))+ (and (p "init" 1 z1) (p "init" "b" z1 b)))))+ (comment "Responder point of view")+ (comment "Failed authentication goal: agreement on name b"))++(defprotocol nsl basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace+ (send (enc n1 a (pubk b)))+ (recv (enc n1 n2 b (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace+ (recv (enc n1 a (pubk b)))+ (send (enc n1 n2 b (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder-Lowe with no role origination assumptions"))++(defgoal nsl+ (forall ((a b name) (n2 text) (z0 node))+ (implies+ (and (p "resp" 2 z0) (p "resp" "n2" z0 n2)+ (p "resp" "a" z0 a) (p "resp" "b" z0 b)+ (non (privk a)) (uniq n2))+ (exists ((z1 node))+ (and (p "init" 1 z1) (p "init" "b" z1 b)))))+ (comment "Responder point of view")+ (comment "Authentication goal: agreement on name b"))++(defgoal ns+ (forall ((a b name) (n1 text) (z0 z1 node))+ (implies+ (and (p "init" 2 z0) (p "init" "n1" z0 n1)+ (p "init" "a" z0 a) (p "init" "b" z0 b)+ (p "" 0 z1) (p "" "x" z1 n1)+ (non (privk a)) (non (privk b)) (uniq n1))+ (false)))+ (comment "Initiator point of view")+ (comment "Secrecy goal: nonce n1 not revealed"))++(defprotocol unilateral basic+ (defrole init+ (vars (a name) (n text))+ (trace+ (send (enc n (pubk a)))+ (recv n)))+ (defrole resp+ (vars (a name) (n text))+ (trace+ (recv (enc n (pubk a)))+ (send n)))+ (comment "Unilateral authentication"))++(defgoal unilateral+ (forall ((a name) (n text)+ (z0 node))+ (implies+ (and (p "init" 1 z0)+ (p "init" "n" z0 n)+ (p "init" "a" z0 a)+ (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1)+ (p "resp" "a" z1 a)))))+ (comment "Unilateral authentication goal"))++;;; Does initiator satisfy the unilateral authentication goal?++;;; Note that the goal requires translation of some of the role+;;; specific predicates.+(defgoal ns+ (forall ((a name) (n text) (z0 node))+ (implies+ (and (p "init" 1 z0) (p "init" "n1" z0 n)+ (p "init" "b" z0 a) (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "b" z1 a)))))+ (comment "Initiator authentication goal")+ (comment "Same as unilateral goal under the predicate mapping:")+ (comment (p "init" "n") "->" (p "init" "n1") "and")+ (comment (p "init" "a") "->" (p "init" "b") "and")+ (comment (p "resp" "a") "->" (p "resp" "b")))++;;; Does responder satisfy the unilateral authentication goal?++(defgoal ns+ (forall ((a name) (n text) (z0 node))+ (implies+ (and (p "resp" 2 z0) (p "resp" "n2" z0 n)+ (p "resp" "a" z0 a) (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "init" 2 z1) (p "init" "a" z1 a)))))+ (comment "Responder authentication goal")+ (comment "Same as unilateral goal under the predicate mapping:")+ (comment (p "init" 1) "->" (p "resp" 2) "and")+ (comment (p "init" "n") "->" (p "resp" "n2") "and")+ (comment (p "init" "a") "->" (p "resp" "a") "and")+ (comment (p "resp" 1) "->" (p "init" 2) "and")+ (comment (p "resp" "a") "->" (p "init" "a")))++(defgoal ns+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and+ (p "init" 1 z0) (p "init" "n1" z0 n)+ (p "init" "a" z0 a) (p "init" "b" z0 b)+ (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "b" z1 b)))))+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and+ (p "init" 1 z0) (p "init" "n1" z0 n)+ (p "init" "a" z0 a) (p "init" "b" z0 b)+ (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "a" z1 a)))))+ (comment "Two initiator authentication goals"))++;;; The shape analysis sentence as input (kind of useless)++(defgoal ns+ (forall ((n1 n2 text) (b a name) (z z-0 node))+ (implies+ (and (p "init" 0 z) (p "init" 2 z-0)+ (p "init" "n1" z-0 n1) (p "init" "n2" z-0 n2)+ (p "init" "a" z-0 a) (p "init" "b" z-0 b)+ (str-prec z z-0) (non (privk b)) (uniq-at n1 z))+ (exists ((n2-0 text) (z-1 z-2 z-3 node))+ (and (p "init" 1 z-1) (p "resp" 0 z-2)+ (p "resp" 1 z-3) (p "resp" "n2" z-3 n2-0)+ (p "resp" "n1" z-3 n1) (p "resp" "b" z-3 b)+ (p "resp" "a" z-3 a) (prec z z-2) (prec z-3 z-1)+ (str-prec z z-1) (str-prec z-1 z-0)+ (str-prec z-2 z-3)))))+ (comment "Shape analysis sentence"))++;;; Section 2 --- Additional Examples++(defgoal ns+ (forall ((a b name) (n2 text) (z0 z1 node))+ (implies+ (and+ (p "resp" 2 z0) (p "resp" "n2" z0 n2)+ (p "resp" "a" z0 a) (p "resp" "b" z0 b)+ (p "" 0 z1) (p "" "x" z1 n2)+ (non (privk a)) (non (privk b)) (uniq n2))+ (false)))+ (comment "Responder point of view")+ (comment "Failed secrecy goal: nonce n2 not revealed"))++;;; Double initiator point of view+(defskeleton ns+ (vars (a b name) (n1 n1-0 text))+ (defstrand init 3 (a a) (b b) (n1 n1))+ (defstrand init 3 (a a) (b b) (n1 n1-0))+ (non-orig (privk b) (privk a))+ (uniq-orig n1 n1-0)+ (goals+ (forall ((n1 n1-0 n2 n2-0 text) (a b name) (z z-0 z-1 z-2 node))+ (implies+ (and+ (p "init" 0 z) (p "init" 2 z-0) (p "init" 0 z-1)+ (p "init" 2 z-2) (p "init" "n1" z-0 n1) (p "init" "n2" z-0 n2)+ (p "init" "a" z-0 a) (p "init" "b" z-0 b)+ (p "init" "n1" z-2 n1-0) (p "init" "n2" z-2 n2-0)+ (p "init" "a" z-2 a) (p "init" "b" z-2 b) (str-prec z z-0)+ (str-prec z-1 z-2) (non (privk a)) (non (privk b))+ (uniq-at n1 z) (uniq-at n1-0 z-1))+ (= z-1 z))))+ (comment "Double initiator point of view"))++(defprotocol nsl-typeless basic+ (defrole init+ (vars (a b name) (n1 text) (n2 mesg))+ (trace+ (send (enc a n1 (pubk b)))+ (recv (enc n1 n2 b (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 text) (n1 mesg))+ (trace+ (recv (enc a n1 (pubk b)))+ (send (enc n1 n2 b (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder-Lowe with untyped nonces"))++;;; The responder point of view+(defgoal nsl-typeless+ (forall ((n2 text) (a b name) (z z-0 node))+ (implies+ (and (p "resp" 1 z) (p "" 0 z-0)+ (p "resp" "n2" z n2) (p "resp" "b" z b) (p "resp" "a" z a)+ (p "" "x" z-0 n2) (non (privk a)) (non (privk b)) (uniq n2))+ (false)))+ (comment "Shows typeflaw in typeless NSL"))++(defskeleton ns+ (vars (a name) (n2 text))+ (defstrand resp 3 (a a) (n2 n2))+ (non-orig (privk a))+ (uniq-orig n2)+ (goals+ (forall ((n1 n2 text) (a b name) (z z-0 node))+ (implies+ (and (p "init" 0 z) (p "init" 2 z-0)+ (p "init" "n1" z-0 n1) (p "init" "n2" z-0 n2)+ (p "init" "a" z-0 a) (p "init" "b" z-0 b)+ (str-prec z z-0) (non (privk a)) (non (privk b))+ (uniq-at n1 z))+ (exists ((z-1 z-2 z-3 node))+ (and (p "init" 1 z-1) (p "resp" 0 z-2)+ (p "resp" 1 z-3) (p "resp" "n2" z-3 n2)+ (p "resp" "n1" z-3 n1) (p "resp" "b" z-3 b)+ (p "resp" "a" z-3 a) (prec z z-2) (prec z-3 z-1)+ (str-prec z z-1) (str-prec z-1 z-0)+ (str-prec z-2 z-3))))))+ (comment "Responder point of view with SAS"))++(defskeleton ns+ (vars (a name) (n2 text))+ (defstrand resp 3 (a a) (n2 n2))+ (non-orig (privk a))+ (uniq-orig n2)+ (goals+ (forall ((n1 n2 text) (a b name) (z z-0 node))+ (implies+ (and (p "init" 0 z) (p "init" 2 z-0)+ (p "init" "n1" z-0 n1) (p "init" "n2" z-0 n2)+ (p "init" "a" z-0 a) (p "init" "b" z-0 b)+ (str-prec z z-0) (non (privk a)) (non (privk b))+ (uniq-at n1 z))+ (false))))+ (comment "Responder point of view with false as the conclusion"))++(defskeleton ns+ (vars (a b name) (n1 text))+ (defstrand init 3 (a a) (b b) (n1 n1))+ (non-orig (privk b) (privk a))+ (uniq-orig n1)+ (goals+ (forall ((n1 n2 text) (a b name) (z z-0 node))+ (implies+ (and (p "init" 0 z) (p "init" 2 z-0)+ (p "init" "n1" z-0 n1) (p "init" "n2" z-0 n2)+ (p "init" "a" z-0 a) (p "init" "b" z-0 b)+ (str-prec z z-0) (non (privk a)) (non (privk b))+ (uniq-at n1 z))+ (false))))+ (comment "Initiator point of view with false as the conclusion"))++(defgoal ns+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and+ (p "resp" 2 z0) (p "resp" "n2" z0 n)+ (p "resp" "a" z0 a) (p "resp" "b" z0 b)+ (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node))+ (and (p "init" 2 z1) (p "init" "a" z1 a)))))+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and+ (p "resp" 2 z0) (p "resp" "n2" z0 n)+ (p "resp" "a" z0 a) (p "resp" "b" z0 b)+ (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node))+ (and (p "init" 2 z1) (p "init" "b" z1 b)))))+ (comment "Two responder authentication goals"))++;;; Needham-Schroeder Protocol with origination assumptions on roles++(defprotocol ns-role-origs basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace+ (send (enc n1 a (pubk b)))+ (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ (non-orig (privk b))+ (uniq-orig n1))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace+ (recv (enc n1 a (pubk b)))+ (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ (non-orig (privk a))+ (uniq-orig n2))+ (comment "Needham-Schroeder with role assumptions that are too strong"))++;;; The initiator point of view+(defskeleton ns-role-origs+ (vars)+ (defstrand init 3))++;;; The responder point of view+(defskeleton ns-role-origs+ (vars)+ (defstrand resp 3))++;;; Needham-Schroeder Protocol with a doubled nonce. Look at the+;;; first message in each role.++(defprotocol ns2 basic+ (defrole init+ (vars (a b name) (n1 n2 n3 text))+ (trace+ (send (enc n1 n3 a (pubk b)))+ (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace+ (recv (enc n1 n1 a (pubk b)))+ (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ (note doubled nonce in the first message))+ (note that this protocol is derived from Needham-Schroeder))++(defskeleton ns2+ (vars (a b name) (n1 text))+ (defstrand init 3 (a a) (b b) (n1 n1))+ (non-orig (privk b) (privk a))+ (uniq-orig n1)+ (note the disappearance of this note))++;;; Note that the association list style key-value pairs that follow+;;; the list of strands can be supplied in any order, and values with+;;; the same key are appended together. Check the output to see how+;;; CPSA interprets this input.+(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n2 n2) (n1 n1) (b b) (a a))+ (non-orig (privk b))+ (precedes ((0 0) (1 0)))+ (non-orig (privk a))+ (uniq-orig n1)+ (precedes ((1 1) (0 1))))
doc/index.html view
@@ -10,17 +10,19 @@ <p>[<a href="cpsauser.html">CPSA User Guide</a>] [<a href="cpsaprimer.pdf">CPSA Primer</a>]+[<a href="cpsagoals.pdf">CPSA and Formal Security Goals</a>] [<a href="cpsaoverview.pdf">CPSA Overview</a>] [<a href="cpsaintroslides.pdf">CPSA Introductory Slides</a>] [<a href="http://www.mitre.org/publications/technical-papers/completeness-of-cpsa">CPSA Correctness Proof</a>]</p> <h1>CPSA</h1> -<p>The Cryptographic Protocol Shapes Analyzer (CPSA) attempts to enumerate all-essentially different executions possible for a cryptographic protocol. We call-them the <i>shapes</i> of the protocol. Naturally occurring protocols have only-finitely many, indeed very few shapes. Authentication and secrecy properties-are easy to determine from them, as are attacks and anomalies.</p>+<p>The Cryptographic Protocol Shapes Analyzer (CPSA) attempts to+ enumerate all essentially different executions possible for a+ cryptographic protocol. We call them the <i>shapes</i> of the+ protocol. Naturally occurring protocols have only finitely many,+ indeed very few shapes. Authentication and secrecy properties are+ easy to determine from them, as are attacks and anomalies.</p> <p>CPSA comes with a user guide, a primer, an overview, and some slides. The user guide provides usage information for each program in the@@ -47,11 +49,11 @@ better way to analyze protocols when GNU Make is available.</p> <p>After running the analysis, you will note files with the extension-<code>.xhtml</code>. These are XHTML/SVG compound documents that can be viewed by-standards compliant browsers such as Firefox, Chrome, Safari, and-later versions of Internet Explorer. See the section-on <a href="cpsauser.html#cpsagraph">visualization</a> in the user-guide for help interpreting these documents.</p>+ <code>.xhtml</code>. These are XHTML/SVG compound documents that can+ be viewed by standards compliant browsers such as Firefox, Chrome,+ Safari, and later versions of Internet Explorer. See the section+ on <a href="cpsauser.html#cpsagraph">visualization</a> in the user+ guide for help interpreting these documents.</p> <p>New users should study CPSA's analysis of the following protocols in order, Blanchet (<code>blanchet.xhtml</code>), Needham-Schroeder@@ -60,8 +62,13 @@ (<code>ffgg.xhtml</code>), and finally Otway-Rees (<code>or.xhtml</code>). When studying the full output, simultaneously display the extracted shapes. The shapes file has an- extension of <code>_shapes.xhtml</code>.</p>+ extension of <code>_shapes.xhtml</code>. +<p>An analysis of Needham-Schroeder+ using <a href="cpsagoals.pdf">security goals</a> is+ in <code>goals.xhtml</code>. This example can safely be ignored by+ new users.</p>+ <p>To make effective use of CPSA, new users should scan the <a href="cpsauser.html">user guide</a> to get a flavor of its contents, and then read the <a href="cpsaprimer.pdf">primer</a>.@@ -70,9 +77,9 @@ <h2>Tips</h2> -<p>Choose a small, simple protocol for your first analysis task. When analyzing-complex protocols, analyze small parts of the protocol first, and then enrich-the description of the problem. </p>+<p>Choose a small, simple protocol for your first analysis task. When+ analyzing complex protocols, analyze small parts of the protocol+ first, and then enrich the description of the problem. </p> <p>The source distribution contains additional programs and a test suite with many examples. The README in the top-level directory of@@ -92,10 +99,11 @@ Specification</a>.</p> <p>An origination assumption- (<code>non-orig</code>, <code>pen-non-orig</code>, and <code>unig-orig</code>),- can be specified in a role or in a skeleton. Be sure to read the- advice in the <a href="cpsaprimer.pdf">primer</a> on the proper- placement of origination assumptions.</p>+ (<code>non-orig</code>, <code>pen-non-orig</code>,+ and <code>unig-orig</code>), can be specified in a role or in a+ skeleton. Be sure to read the advice in+ the <a href="cpsaprimer.pdf">primer</a> on the proper placement of+ origination assumptions.</p> <p>Variables of sort message unify with any message. See Otway-Rees (<code>or.xhtml</code>) for an example of the use of variables of this@@ -110,15 +118,18 @@ multiple occurrences of a message with one named definition of it. Macros are described in the <a href="cpsaprimer.pdf">primer</a>.</p> -<p>When the <code>cpsagraph</code> program is given the <code>--zoom</code>- option, it produces diagrams that scale. This is useful when- viewing large diagrams.</p>+<p>When the <code>cpsagraph</code> program is given+ the <code>--zoom</code> option, it produces diagrams that scale.+ This is useful when viewing large diagrams.</p> -<p>The <code>cpsasas</code> program translates a CPSA result into a- sentence in first-order logic that can be used with automated- theorem provers. The formula is called a shape analysis sentence.- See <a href="http://arxiv.org/abs/1204.0480">Deducing Security Goals- From Shape Analysis Sentences</a> for more details.</p>+<p>In CPSA, a security goal is expressed as a sentence in first-order+ logic. It asserts that if some properties hold for a skeleton, then+ some other properties must hold for all shapes computed by CPSA+ starting with the skeleton. Security goals can be used to state+ authentication and secrecy goals of a protocol. See+ <a href="cpsagoals.pdf">CPSA and Formal Security Goals</a>. An+ analysis of Needham-Schroeder using first-order logic is+ in <code>goals.xhtml</code>.</p> <p>When the <code>cpsapp</code> program is given the <code>--json</code> option, it translates S-expressions into
doc/macros.tex view
@@ -1,5 +1,5 @@ \newcommand{\cpsa}{\textsc{cpsa}}-\newcommand{\version}{2.4.0}+\newcommand{\version}{2.5.0} \newcommand{\cpsacopying}{\begingroup \renewcommand{\thefootnote}{}\footnotetext{{\copyright} 2010 The MITRE Corporation. Permission to copy without fee all or part of@@ -58,3 +58,5 @@ \newcommand{\longtwoheadrightarrow}{\relax \smash{\relbar\joinrel\twoheadrightarrow}\vphantom\rightarrow} \newcommand{\setreduction}[1]{\stackrel{#1}{\longtwoheadrightarrow}}+\newcommand{\uniqat}{\mbox{\sf uniq-at}}+\newcommand{\strprec}{\mbox{\sf str-prec}}
src/CPSA/Basic/Algebra.hs view
@@ -4,6 +4,10 @@ -- order-sorted algebra. It exports a name, and the origin used to -- generate variables. +-- To support security goals, the message algebra has been augmented+-- with support for variables of sort node and pairs of integers. The+-- constructor D is used as N is taken for numbers in S-Expressions.+ -- Copyright (c) 2009 The MITRE Corporation -- -- This program is free software: you can redistribute it and/or@@ -122,6 +126,8 @@ = I !Id | C !String -- Tag constants | F !Symbol ![Term]+ | D !Id -- Node variable+ | P (Int, Int) -- Node constant deriving (Show, Eq, Ord) -- In this algebra (F Invk [F Invk [t]]) == t is an axiom@@ -132,7 +138,7 @@ -- sort information is called a variable. The sort of a variable is -- one of mesg, text, data, name, skey, and akey. --- Terms that represent variables.+-- Terms that represent algebra variables. isVar :: Term -> Bool isVar (I _) = True -- Sort: mesg isVar (F s [I _]) =@@ -140,6 +146,11 @@ s == Text || s == Data || s == Name || s == Skey || s == Akey isVar _ = False +-- Note that isVar of (D _) is false.+isNodeVar :: Term -> Bool+isNodeVar (D _) = True+isNodeVar _ = False+ -- Extract the identifier from a variable varId :: Term -> Id varId (I x) = x@@ -148,6 +159,7 @@ varId (F Name [I x]) = x varId (F Skey [I x]) = x varId (F Akey [I x]) = x+varId (D x) = x varId _ = error "Algebra.varId: term not a variable with its sort" isAcquiredVar :: Term -> Bool@@ -246,6 +258,8 @@ isAtom (C _) = False isAtom (F s _) = s == Text || s == Data || s == Name || s == Skey || s == Akey+isAtom (D _) = False+isAtom (P _) = False -- Does a term occur in another term? occursIn :: Term -> Term -> Bool@@ -277,6 +291,7 @@ foldVars f (foldVars f acc t0) t1 foldVars f acc (F Hash [t]) = -- Hashing foldVars f acc t+foldVars f acc t@(D _) = f acc t -- Node variable foldVars _ _ t = error $ "Algebra.foldVars: Bad term " ++ show t -- Fold f through a term applying it to each term that is carried by the term.@@ -437,6 +452,7 @@ isVar = isVar isAcquiredVar = isAcquiredVar isAtom = isAtom+ isNodeVar = isNodeVar termsWellFormed = termsWellFormed occursIn = occursIn foldVars = foldVars@@ -534,6 +550,13 @@ let (alist', gen', u') = foldl cloneTermList (alist, gen, []) u in (alist', gen', F sym $ reverse u')+ D x -> -- identifiers to identifier.+ case lookup x alist of+ Just y -> (alist, gen, D y)+ Nothing ->+ let (gen', y) = cloneId gen x in+ ((x, y) : alist, gen', D y)+ P p -> (alist, gen, P p) cloneTermList (alist, gen, u) t = let (alist', gen', t') = cloneTerm (alist, gen) t in (alist', gen', t' : u)@@ -561,6 +584,9 @@ t -> F Invk [t] idSubst subst (F s u) = F s (map (idSubst subst) u)+idSubst subst (D x) =+ M.findWithDefault (D x) x subst+idSubst _ t@(P _) = t -- Unification and substitution @@ -606,6 +632,10 @@ case M.lookup x s of Nothing -> I x Just t -> chase (Subst s) t+chase (Subst s) (D x) =+ case M.lookup x s of+ Nothing -> D x+ Just t -> chase (Subst s) t chase s (F Invk [t]) = chaseInvk s t chase _ t = t @@ -622,6 +652,8 @@ occurs x (I y) = x == y occurs _ (C _) = False occurs x (F _ u) = any (occurs x) u+occurs x (D y) = x == y+occurs _ (P _) = False unifyChase :: Term -> Term -> Subst -> Maybe Subst unifyChase t t' s = unifyTerms (chase s t) (chase s t') s@@ -648,6 +680,15 @@ unifyTerms (F sym u) (F sym' u') s | sym == sym' = unifyTermLists u u' s | otherwise = Nothing+unifyTerms (D x) (D y) (Subst s)+ | x == y = Just (Subst s)+ | otherwise = Just (Subst $ M.insert x (D y) s)+unifyTerms (D x) (P p) (Subst s) =+ Just (Subst $ M.insert x (P p) s)+unifyTerms t (D x) s = unifyTerms (D x) t s+unifyTerms (P p) (P p') s+ | p == p' = Just s+ | otherwise = Nothing unifyTerms _ _ _ = Nothing unifyTermLists :: [Term] -> [Term] -> Subst -> Maybe Subst@@ -684,6 +725,8 @@ t -> F Invk [t] F s u -> F s (map (substChase subst) u)+ t@(D _) -> t+ t@(P _) -> t instance C.Subst Term Gen Subst where emptySubst = emptySubst@@ -720,6 +763,11 @@ | s == s' = matchLists u u' r match (F Invk [t]) t' r = match t (F Invk [t']) r+match (D x) t (Env r) =+ case M.lookup x r of+ Nothing -> Just $ Env $ M.insert x t r+ Just t' -> if t == t' then Just $ Env r else Nothing+match (P p) (P p') r = if p == p' then Just r else Nothing match _ _ _ = Nothing matchLists :: [Term] -> [Term] -> Env -> Maybe Env@@ -744,6 +792,8 @@ allId f (I x) = f x allId _ (C _) = True allId f (F _ u) = all (allId f) u+allId f (D x) = f x+allId _ (P _) = True -- Cast an environment into a substitution by filtering out trivial -- bindings.@@ -773,6 +823,8 @@ | x == y = (F Skey [I x], F Skey [t]) loop (F Akey [I x] : _) (y, t) | x == y = (F Akey [I x], F Akey [t])+ loop (D x : _) (y, t)+ | x == y = (D x, t) loop (_ : domain) pair = loop domain pair -- Ensure the range of an environment contains only variables and that@@ -786,6 +838,15 @@ S.notMember x s && loop (S.insert x s) e loop _ _ = False +nodeMatch :: Term -> (Int, Int) -> Env -> Maybe Env+nodeMatch t p env = match t (P p) env++nodeLookup :: Env -> Term -> Maybe (Int, Int)+nodeLookup env t =+ case instantiate env t of+ P p -> Just p+ _ -> Nothing+ instance C.Env Term Gen Subst Env where emptyEnv = emptyEnv instantiate = instantiate@@ -799,6 +860,9 @@ substitution = substitution reify = reify matchRenaming (_, e) = matchRenaming e+ nodeMatch t t' (g, e) =+ maybe [] (\e -> [(g, e)]) $ nodeMatch t t' e+ nodeLookup = nodeLookup -- Term specific loading functions @@ -824,17 +888,18 @@ Left _ -> do let (gen', x) = freshId gen name- p <- mkVar (I x)+ p <- mkVar x return (gen', p : vars) where- mkVar t =+ mkVar x = case sort of- "mesg" -> return t- "text" -> return $ F Text [t]- "data" -> return $ F Data [t]- "name" -> return $ F Name [t]- "skey" -> return $ F Skey [t]- "akey" -> return $ F Akey [t]+ "mesg" -> return (I x)+ "text" -> return $ F Text [I x]+ "data" -> return $ F Data [I x]+ "name" -> return $ F Name [I x]+ "skey" -> return $ F Skey [I x]+ "akey" -> return $ F Akey [I x]+ "node" -> return (D x) _ -> fail (shows pos' "Sort " ++ sort ++ " not recognized") loadVar _ (x,_) = fail (shows (annotation x) "Bad variable syntax") @@ -976,6 +1041,7 @@ displayVar ctx (F Name [I x]) = displaySortId "name" ctx x displayVar ctx (F Skey [I x]) = displaySortId "skey" ctx x displayVar ctx (F Akey [I x]) = displaySortId "akey" ctx x+displayVar ctx (D x) = displaySortId "node" ctx x displayVar _ _ = error "Algebra.displayVar: term not a variable with its sort" @@ -1015,6 +1081,8 @@ L () (S () "enc" : displayEnc ctx t0 t1) displayTerm ctx (F Hash [t]) = L () (S () "hash" : displayList ctx t)+displayTerm ctx (D x) = displayId ctx x+displayTerm _ (P (z, i)) = L () [N () z, N () i] displayTerm _ t = error ("Algebra.displayTerm: Bad term " ++ show t) displayList :: Context -> Term -> [SExpr ()]
src/CPSA/DiffieHellman/Algebra.hs view
@@ -813,6 +813,7 @@ isVar = isVar isAcquiredVar = isAcquiredVar isAtom = isAtom+ isNodeVar _ = error "Algebra.isNodeVar: no support for nodes" termsWellFormed = termsWellFormed occursIn = occursIn foldVars = foldVars@@ -1715,6 +1716,8 @@ substitution = substitution reify = reify matchRenaming = matchRenaming+ nodeMatch _ _ _ = error "Algebra.nodeMatch: no support for nodes"+ nodeLookup _ _ = error "Algebra.nodeMatch: no support for nodes" -- Term specific loading functions
src/CPSA/Lib/Algebra.hs view
@@ -26,10 +26,16 @@ -- Terms class (Ord t, Show t) => Term t where- isVar :: t -> Bool -- Is term a variable in the algebra?++ -- These predicates succeed only on terms in the message algebra.+ isVar :: t -> Bool -- Is term a variable in the message algebra? isAcquiredVar :: t -> Bool -- Is term an acquired variable? isAtom :: t -> Bool -- Is the sort of this term a base sort? + -- Extension for security goals, a predicate that succeeds only+ -- when applied to node variables.+ isNodeVar :: t -> Bool+ -- Does a term occur in another term? occursIn :: t -> t -> Bool @@ -133,7 +139,7 @@ -- Given a generator, load a list of variables or return an error -- message. Each element of the list is an identifier and a sort.- -- The varibles are returned in the reverse order.+ -- The variables are returned in the reverse order. loadVars :: Monad m => g -> [SExpr Pos] -> m (g, [t]) -- Substitutions@@ -169,6 +175,12 @@ -- Is match a one-to-one variable-to-variable map? This function -- is used while testing if two skeletons are isomorphic. matchRenaming :: (g, e) -> Bool+ -- Extensions for security goals: node match. To succeed, the+ -- term must be a variable of sort node.+ nodeMatch :: t -> (Int, Int) -> (g, e) -> [(g, e)]+ -- Node lookup. If t is a node variable and is bound to a pair in+ -- e, then return the pair, otherwise return nothing.+ nodeLookup :: e -> t -> Maybe (Int, Int) -- Display contexts--maps from variables to their printed representation.
+ src/CPSA/Lib/Characteristic.hs view
@@ -0,0 +1,248 @@+-- Makes the characteristic skeleton of a security goal++-- Copyright (c) 2015 The MITRE Corporation+--+-- This program is free software: you can redistribute it and/or+-- modify it under the terms of the BSD License as published by the+-- University of California.++module CPSA.Lib.Characteristic (Conj, characteristic) where++import Control.Monad+import qualified Data.List as L+import CPSA.Lib.Utilities+import CPSA.Lib.SExpr+import CPSA.Lib.Algebra+import CPSA.Lib.Protocol+import CPSA.Lib.Goal+import CPSA.Lib.Strand++{--+import System.IO.Unsafe+z :: Show a => a -> b -> b+z x y = unsafePerformIO (print x >> return y)+--}++type Conj t = [(Pos, AForm t)]++-- Entry point. Takes a position, a protocol, a variable generator, a+-- goal, and a skeleton comment and makes a skeleton or fails. This+-- function extracts the anecedent and univesally quantified variable.+characteristic :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ [Goal t] -> g -> Conj t -> [SExpr ()] -> m (Preskel t g s e)+characteristic pos prot goals g antec comment =+ equalsForm pos prot goals g antec comment++-- Checks for equals in an antecedent and fails if it finds one. One+-- could use unification to solve the equality, and then apply the+-- result to the remaining parts of the formula.+equalsForm :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ [Goal t] -> g -> Conj t -> [SExpr ()] -> m (Preskel t g s e)+equalsForm pos _ _ _ as _ | any isEquals as =+ fail (shows pos "Equals not allowed in antecedent")+equalsForm pos prot goals g as comment =+ splitForm pos prot goals g as comment++isEquals :: (Pos, AForm t) -> Bool+isEquals (_, Equals _ _) = True+isEquals _ = False++-- Split the formula into instance formulas and skeleton formulas.+-- The instance formulas are used to generate the skeleton's+-- instances, and the skeleton formulas generate the rest. Make the+-- instances, and then make the rest.+splitForm :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ [Goal t] -> g -> Conj t -> [SExpr ()] -> m (Preskel t g s e)+splitForm pos prot goals g as comment =+ do+ (nmap, g, insts) <- mkInsts g is+ mkSkel pos prot goals nmap g insts ks comment+ where -- is is the instance formulas and+ (is, ks) = L.partition instForm as -- ks is the skeleton formulas++-- Instance formulas are role predicates, parameter predicates, and+-- strand prec.+instForm :: (Pos, AForm t) -> Bool+instForm (_, RolePred _ _ _) = True+instForm (_, ParamPred _ _ _ _) = True+instForm (_, StrPrec _ _) = True+instForm _ = False++-- Make the instances from the instance predicates++mkInsts :: (Algebra t p g s e c, Monad m) => g -> Conj t ->+ m ([(t, Node)], g, [Instance t e])+mkInsts g as =+ do+ nri <- nodeRoleIndex as -- Compute index and role of each node+ nss <- binNodes nri as -- Collect nodes on the same strand+ (g, insts) <- foldInsts g as nri nss -- Construct instances+ return (nodeMap nri nss, g, insts) -- Construct node map for later use++type RoleIndex t = (Role t, Int)++-- Computes a map from nodes to role-index pairs+nodeRoleIndex :: (Eq t, Monad m) => Conj t -> m [(t, RoleIndex t)]+nodeRoleIndex as =+ foldM f [] as+ where+ f nri (pos, RolePred r i n) =+ case lookup n nri of+ Nothing -> return ((n, (r, i)) : nri)+ Just _ -> fail (shows pos+ "Node occurs in more than one role predicate")+ f nri _ = return nri++-- Use this lookup when lookup must succeed.+nriLookup :: Eq t => t -> [(t, RoleIndex t)] -> RoleIndex t+nriLookup n nri =+ case lookup n nri of+ Just ri -> ri+ Nothing -> error "Characteristic.nriLookup: Bad lookup"++--- Use str-prec to collect the nodes on the same strand. Check to+--- make sure the role associated with nodes is the same.+binNodes :: (Eq t, Monad m) => [(t, RoleIndex t)] -> Conj t -> m [[t]]+binNodes nri as =+ foldM f (map (\(x, _) -> [x]) nri) as+ where+ f nss (pos, StrPrec n n')+ | i >= i' || rname r /= rname r' =+ fail (shows pos "Bad str-prec")+ | otherwise = return $ merge n n' nss+ where+ (r, i) = nriLookup n nri+ (r', i') = nriLookup n' nri+ f nss _ = return nss++-- Merge two sets of nodes and delete the old sets+merge :: Eq t => t -> t -> [[t]] -> [[t]]+merge n n' nss =+ (ns ++ ns') : L.delete ns (L.delete ns' nss)+ where+ ns = findl n nss+ ns' = findl n' nss++-- Find a set containing node n+findl :: Eq t => t -> [[t]] -> [t]+findl n nss =+ case L.find (elem n) nss of+ Just ns -> ns+ Nothing -> error "Characteristic.findl: cannot find a node"++-- Construct instances+foldInsts :: (Algebra t p g s e c, Monad m) => g -> Conj t ->+ [(t, RoleIndex t)] -> [[t]] -> m (g, [Instance t e])+foldInsts g _ _ [] = return (g, [])+foldInsts g as nri (ns : nss) =+ do+ (g, inst) <- mkInst g as nri ns+ (g, insts) <- foldInsts g as nri nss+ return (g, inst : insts)++-- Construct an instance by extracting maplets from the parameter+-- predicates with nodes associated with the strand.+mkInst :: (Algebra t p g s e c, Monad m) => g -> Conj t ->+ [(t, RoleIndex t)] -> [t] -> m (g, Instance t e)+mkInst _ _ _ [] = error "Characteristic.mkInst: no nodes"+mkInst g as nri (n : ns)+ | h < 1 || h > length (rtrace r) = -- Checked by the the loader+ error "Character.mkInst: Bad height"+ | otherwise =+ do+ (g, env) <- foldM (mkMaplet r (n : ns)) (g, emptyEnv) as+ return (mkInstance g r env h)+ where+ (r, i) = nriLookup n nri+ -- The height (1 + max index)+ h = 1 + foldr f i ns+ f n i = max i (snd $ nriLookup n nri)++-- Add match from a maplet+mkMaplet :: (Algebra t p g s e c, Monad m) => Role t ->+ [t] -> (g, e) -> (Pos, AForm t) -> m (g, e)+mkMaplet role ns env (pos, ParamPred r v n t)+ | elem n ns =+ if rname role == rname r then -- Ensure role match the one+ case match v t env of -- used to create instance+ env : _ -> return env+ [] -> fail (shows pos "Domain does not match range")+ else+ fail (shows pos+ "Role in parameter pred differs from role position pred")+mkMaplet _ _ env _ = return env++-- Generate a map from node variables to node constants.+nodeMap :: Eq t => [(t, RoleIndex t)] -> [[t]] -> [(t, Node)]+nodeMap nri nss =+ [ (n, (z, i)) |+ (z, ns) <- zip [0..] nss,+ n <- ns,+ let (_, i) = nriLookup n nri ]++-- Use this lookup when lookup must succeed, that is when loader makes+-- the check.+nMapLookup :: Eq t => t -> [(t, Node)] -> Node+nMapLookup n nmap =+ case lookup n nmap of+ Just n -> n+ Nothing -> error "Characteristic.nMapLookup: Bad lookup"++-- Create a skeleton given a list of instances++mkSkel :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ [Goal t] -> [(t, Node)] -> g -> [Instance t e] ->+ Conj t -> [SExpr ()] -> m (Preskel t g s e)+mkSkel pos p goals nmap g insts as comment =+ do+ let o = foldr (mkPrec nmap) [] as+ let nr = foldr mkNon [] as+ let ar = foldr mkPnon [] as+ let ur = foldr mkUniq [] as+ let (nr', ar', ur') = foldl addInstOrigs (nr, ar, ur) insts+ let prios = []+ let k = mkPreskel g p goals insts o nr' ar' ur' prios comment+ mapM_ (checkUniqAt nmap k) as+ case termsWellFormed $ nr' ++ ar' ++ ur' ++ kterms k of+ False -> fail (shows pos "Terms in skeleton not well formed")+ True -> return ()+ case verbosePreskelWellFormed k of+ Right () -> return k+ Left msg -> fail $ shows pos+ $ showString "Skeleton not well formed: " msg++addInstOrigs :: Algebra t p g s e c => ([t], [t], [t]) ->+ Instance t e -> ([t], [t], [t])+addInstOrigs (nr, ar, ur) i =+ (foldl (flip adjoin) nr $ inheritRnon i,+ foldl (flip adjoin) ar $ inheritRpnon i,+ foldl (flip adjoin) ur $ inheritRunique i)++mkPrec :: Eq t => [(t, (Int, Int))] ->+ (Pos, AForm t) -> [Pair] -> [Pair]+mkPrec nmap (_, Prec n n') o =+ (nMapLookup n nmap, nMapLookup n' nmap) : o+mkPrec _ _ o = o++mkNon :: (Pos, AForm t) -> [t] -> [t]+mkNon (_, Non t) ts = t : ts+mkNon _ ts = ts++mkPnon :: (Pos, AForm t) -> [t] -> [t]+mkPnon (_, Pnon t) ts = t : ts+mkPnon _ ts = ts++mkUniq :: (Pos, AForm t) -> [t] -> [t]+mkUniq (_, Uniq t) ts = t : ts+mkUniq (_, UniqAt t _) ts = t : ts+mkUniq _ ts = ts++checkUniqAt :: (Algebra t p g s e c, Monad m) => [(t, Node)] ->+ Preskel t g s e -> (Pos, AForm t) -> m ()+checkUniqAt nmap k (pos, UniqAt t n) =+ case lookup t $ korig k of+ Nothing -> fail (shows pos "Atom not unique at node")+ Just ns+ | elem (nMapLookup n nmap) ns -> return ()+ | otherwise -> fail (shows pos "Atom not unique at node")+checkUniqAt _ _ _ = return ()
+ src/CPSA/Lib/Goal.hs view
@@ -0,0 +1,113 @@+-- Security Goals++-- Copyright (c) 2015 The MITRE Corporation+--+-- This program is free software: you can redistribute it and/or+-- modify it under the terms of the BSD License as published by the+-- University of California.++module CPSA.Lib.Goal where++import CPSA.Lib.Protocol++-- Syntax for the atomic formulas+data AForm t+ = RolePred (Role t) Int t+ | ParamPred (Role t) t t t+ | StrPrec t t+ | Prec t t+ | Non t+ | Pnon t+ | Uniq t+ | UniqAt t t+ | Equals t t+ deriving Show++data Goal t+ = Goal { uvars :: [t], -- Universally quantified variables+ antec :: [AForm t], -- Antecedent+ concl :: [[AForm t]] } -- Conclusion++-- Ordering used to sort by constructor order.+aFormOrder :: AForm t -> AForm t -> Ordering+aFormOrder (RolePred _ _ _) (RolePred _ _ _) = EQ+aFormOrder (RolePred _ _ _) (ParamPred _ _ _ _) = LT+aFormOrder (RolePred _ _ _) (StrPrec _ _) = LT+aFormOrder (RolePred _ _ _) (Prec _ _) = LT+aFormOrder (RolePred _ _ _) (Non _) = LT+aFormOrder (RolePred _ _ _) (Pnon _) = LT+aFormOrder (RolePred _ _ _) (Uniq _) = LT+aFormOrder (RolePred _ _ _) (UniqAt _ _) = LT+aFormOrder (RolePred _ _ _) (Equals _ _) = LT+aFormOrder (ParamPred _ _ _ _) (RolePred _ _ _) = GT+aFormOrder (ParamPred _ _ _ _) (ParamPred _ _ _ _) = EQ+aFormOrder (ParamPred _ _ _ _) (StrPrec _ _) = LT+aFormOrder (ParamPred _ _ _ _) (Prec _ _) = LT+aFormOrder (ParamPred _ _ _ _) (Non _) = LT+aFormOrder (ParamPred _ _ _ _) (Pnon _) = LT+aFormOrder (ParamPred _ _ _ _) (Uniq _) = LT+aFormOrder (ParamPred _ _ _ _) (UniqAt _ _) = LT+aFormOrder (ParamPred _ _ _ _) (Equals _ _) = LT+aFormOrder (StrPrec _ _) (RolePred _ _ _) = GT+aFormOrder (StrPrec _ _) (ParamPred _ _ _ _) = GT+aFormOrder (StrPrec _ _) (StrPrec _ _) = EQ+aFormOrder (StrPrec _ _) (Prec _ _) = LT+aFormOrder (StrPrec _ _) (Non _) = LT+aFormOrder (StrPrec _ _) (Pnon _) = LT+aFormOrder (StrPrec _ _) (Uniq _) = LT+aFormOrder (StrPrec _ _) (UniqAt _ _) = LT+aFormOrder (StrPrec _ _) (Equals _ _) = LT+aFormOrder (Prec _ _) (RolePred _ _ _) = GT+aFormOrder (Prec _ _) (ParamPred _ _ _ _) = GT+aFormOrder (Prec _ _) (StrPrec _ _) = GT+aFormOrder (Prec _ _) (Prec _ _) = EQ+aFormOrder (Prec _ _) (Non _) = LT+aFormOrder (Prec _ _) (Pnon _) = LT+aFormOrder (Prec _ _) (Uniq _) = LT+aFormOrder (Prec _ _) (UniqAt _ _) = LT+aFormOrder (Prec _ _) (Equals _ _) = LT+aFormOrder (Non _) (RolePred _ _ _) = GT+aFormOrder (Non _) (ParamPred _ _ _ _) = GT+aFormOrder (Non _) (StrPrec _ _) = GT+aFormOrder (Non _) (Prec _ _) = GT+aFormOrder (Non _) (Non _) = EQ+aFormOrder (Non _) (Pnon _) = LT+aFormOrder (Non _) (Uniq _) = LT+aFormOrder (Non _) (UniqAt _ _) = LT+aFormOrder (Non _) (Equals _ _) = LT+aFormOrder (Pnon _) (RolePred _ _ _) = GT+aFormOrder (Pnon _) (ParamPred _ _ _ _) = GT+aFormOrder (Pnon _) (StrPrec _ _) = GT+aFormOrder (Pnon _) (Prec _ _) = GT+aFormOrder (Pnon _) (Non _) = GT+aFormOrder (Pnon _) (Pnon _) = EQ+aFormOrder (Pnon _) (Uniq _) = LT+aFormOrder (Pnon _) (UniqAt _ _) = LT+aFormOrder (Pnon _) (Equals _ _) = LT+aFormOrder (Uniq _) (RolePred _ _ _) = GT+aFormOrder (Uniq _) (ParamPred _ _ _ _) = GT+aFormOrder (Uniq _) (StrPrec _ _) = GT+aFormOrder (Uniq _) (Prec _ _) = GT+aFormOrder (Uniq _) (Non _) = GT+aFormOrder (Uniq _) (Pnon _) = GT+aFormOrder (Uniq _) (Uniq _) = EQ+aFormOrder (Uniq _) (UniqAt _ _) = LT+aFormOrder (Uniq _) (Equals _ _) = LT+aFormOrder (UniqAt _ _) (RolePred _ _ _) = GT+aFormOrder (UniqAt _ _) (ParamPred _ _ _ _) = GT+aFormOrder (UniqAt _ _) (StrPrec _ _) = GT+aFormOrder (UniqAt _ _) (Prec _ _) = GT+aFormOrder (UniqAt _ _) (Non _) = GT+aFormOrder (UniqAt _ _) (Pnon _) = GT+aFormOrder (UniqAt _ _) (Uniq _) = GT+aFormOrder (UniqAt _ _) (UniqAt _ _) = EQ+aFormOrder (UniqAt _ _) (Equals _ _) = LT+aFormOrder (Equals _ _) (RolePred _ _ _) = GT+aFormOrder (Equals _ _) (ParamPred _ _ _ _) = GT+aFormOrder (Equals _ _) (StrPrec _ _) = GT+aFormOrder (Equals _ _) (Prec _ _) = GT+aFormOrder (Equals _ _) (Non _) = GT+aFormOrder (Equals _ _) (Pnon _) = GT+aFormOrder (Equals _ _) (Uniq _) = GT+aFormOrder (Equals _ _) (UniqAt _ _) = GT+aFormOrder (Equals _ _) (Equals _ _) = EQ
src/CPSA/Lib/Loader.hs view
@@ -9,13 +9,16 @@ module CPSA.Lib.Loader (loadSExprs) where import Control.Monad+import Control.Applicative import qualified Data.List as L import Data.Maybe (isJust) import CPSA.Lib.Utilities import CPSA.Lib.SExpr import CPSA.Lib.Algebra import CPSA.Lib.Protocol+import CPSA.Lib.Goal import CPSA.Lib.Strand+import CPSA.Lib.Characteristic {-- import System.IO.Unsafe@@ -45,6 +48,10 @@ do k <- findPreskel pos ps xs return (ps, k : ks)+loadSExpr _ _ (ps, ks) (L pos (S _ "defgoal" : xs)) =+ do+ k <- findGoal pos ps xs+ return (ps, k : ks) loadSExpr nom origin (ps, ks) (L pos (S pos' "defpreskeleton" : xs)) = loadSExpr nom origin (ps, ks) (L pos (S pos' "defskeleton" : xs)) loadSExpr _ _ (ps, ks) (L _ (S _ "comment" : _)) = return (ps, ks)@@ -62,7 +69,8 @@ do (gen, rs, comment) <- loadRoles origin (x : xs) -- Check for duplicate role names- validate (mkProt name alg gen rs comment) rs+ (gen, r) <- mkListenerRole pos gen+ validate (mkProt name alg gen rs r comment) rs where validate prot [] = return prot validate prot (r : rs) =@@ -119,10 +127,20 @@ Fail msg -> fail (shows pos $ showString "Role not well formed: " msg) loadRole _ pos _ = fail (shows pos "Malformed role") +-- Like Either String but with fail method defined data ReturnFail a = Return a | Fail String +instance Functor (ReturnFail) where+ fmap _ (Fail x) = Fail x+ fmap f (Return y) = Return (f y)++instance Applicative (ReturnFail) where+ pure = Return+ Fail e <*> _ = Fail e+ Return f <*> r = fmap f r+ instance Monad ReturnFail where return = Return Fail l >>= _ = Fail l@@ -192,6 +210,14 @@ showst t = shows $ displayTerm (addToContext emptyContext [t]) t +-- This is the only place a role is generated with an empty name.+-- This is what marks a strand as a listener.+mkListenerRole :: (Algebra t p g s e c, Monad m) => Pos -> g -> m (g, Role t)+mkListenerRole pos g =+ do+ (g, [x]) <- loadVars g [L pos [S pos "x", S pos "mesg"]]+ return (g, mkRole "" [x] [In x, Out x] [] [] [] [] [] False)+ -- Ensure a trace is not a prefix of a listener notListenerPrefix :: Algebra t p g s e c => Trace t -> Bool notListenerPrefix (In t : Out t' : _) | t == t' = False@@ -328,27 +354,31 @@ case x of [term] -> do- (gen, i) <- loadListener kvars gen term+ (gen, i) <- loadListener p kvars gen term loadInsts top p kvars gen (i : insts) xs _ -> fail (shows pos "Malformed deflistener") loadInsts top p kvars gen insts xs = do _ <- alist [] xs -- Check syntax of xs- loadRest top kvars p gen (reverse insts) order nr ar ur pl kcomment+ (gen, gs) <- loadGoals top p gen goals+ loadRest top kvars p gen gs (reverse insts) order nr ar ur pl kcomment where order = assoc "precedes" xs nr = assoc "non-orig" xs ar = assoc "pen-non-orig" xs ur = assoc "uniq-orig" xs pl = assoc "priority" xs- comment = assoc "comment" xs+ goals = assoc "goals" xs kcomment =- if null comment then- []- else- [L () (S () "comment" : map strip comment)]+ loadComment "goals" goals +++ loadComment "comment" (assoc "comment" xs) +loadComment :: String -> [SExpr Pos] -> [SExpr ()]+loadComment _ [] = []+loadComment key comment =+ [L () (S () key : map strip comment)]+ loadInst :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g -> [t] -> g -> String -> Int -> [SExpr Pos] -> m (g, Instance t e)@@ -365,6 +395,8 @@ lookupRole :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g -> String -> m (Role t)+lookupRole _ p role | role == "" =+ return $ listenerRole p lookupRole pos p role = case L.find (\r -> role == rname r) (roles p) of Nothing ->@@ -382,18 +414,18 @@ [] -> fail (shows pos "Domain does not match range") loadMaplet _ _ _ x = fail (shows (annotation x) "Malformed maplet") -loadListener :: (Algebra t p g s e c, Monad m) => [t] -> g ->- SExpr Pos -> m (g, Instance t e)-loadListener kvars gen x =+loadListener :: (Algebra t p g s e c, Monad m) => Prot t g ->+ [t] -> g -> SExpr Pos -> m (g, Instance t e)+loadListener p kvars gen x = do- t <- loadTerm kvars x- return (mkListener gen t)+ t <- loadTerm kvars x+ return $ mkListener p gen t loadRest :: (Algebra t p g s e c, Monad m) => Pos -> [t] ->- Prot t g -> g -> [Instance t e] ->+ Prot t g -> g -> [Goal t] -> [Instance t e] -> [SExpr Pos] -> [SExpr Pos] -> [SExpr Pos] -> [SExpr Pos] -> [SExpr Pos] -> [SExpr ()] -> m (Preskel t g s e)-loadRest pos vars p gen insts orderings nr ar ur pl comment =+loadRest pos vars p gen gs insts orderings nr ar ur pl comment = do case null insts of True -> fail (shows pos "No strands")@@ -405,7 +437,7 @@ ur <- loadBaseTerms vars ur let (nr', ar', ur') = foldl addInstOrigs (nr, ar, ur) insts prios <- mapM (loadPriorities heights) pl- let k = mkPreskel gen p insts o nr' ar' ur' prios comment+ let k = mkPreskel gen p gs insts o nr' ar' ur' prios comment case termsWellFormed $ nr' ++ ar' ++ ur' ++ kterms k of False -> fail (shows pos "Terms in skeleton not well formed") True -> return ()@@ -465,3 +497,268 @@ (foldl (flip adjoin) nr $ inheritRnon i, foldl (flip adjoin) ar $ inheritRpnon i, foldl (flip adjoin) ur $ inheritRunique i)++-- Security goals++-- Load a defgoal form+findGoal :: (Algebra t p g s e c, Monad m) => Pos ->+ [Prot t g] -> [SExpr Pos] -> m (Preskel t g s e)+findGoal pos ps (S _ name : x : xs) =+ case L.find (\p -> name == pname p) ps of+ Nothing -> fail (shows pos $ "Protocol " ++ name ++ " unknown")+ Just p ->+ do+ (g, goal, antec) <- loadSentence pos p (pgen p) x+ let (gs, xs') = findAlist xs+ (g, goals) <- loadGoals pos p g gs+ _ <- alist [] xs' -- Check syntax of xs+ let kcomment =+ loadComment "goals" (x : gs) +++ loadComment "comment" (assoc "comment" xs')+ -- Make and return the characteristic skeleton of a security goal+ characteristic pos p (goal : goals) g antec kcomment+findGoal pos _ _ = fail (shows pos "Malformed goal")++-- Separate argument into goals and any remaining elements of an+-- association list.+findAlist :: [SExpr Pos] -> ([SExpr Pos], [SExpr Pos])+findAlist [] = ([], [])+findAlist (x@(L _ (S _ "forall" : _)) : xs) =+ (x : gs, xs')+ where+ (gs, xs') = findAlist xs+findAlist xs = ([], xs)++--- Load a sequence of security goals++loadGoals :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ g -> [SExpr Pos] -> m (g, [Goal t])+loadGoals _ _ g [] = return (g, [])+loadGoals pos prot g (x : xs) =+ do+ (g, goal, _) <- loadSentence pos prot g x+ (g, goals) <- loadGoals pos prot g xs+ return (g, goal : goals)++-- Load a single security goal, a universally quantified formula+-- Returns the goal and the antecedent with position information.++loadSentence :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ g -> SExpr Pos -> m (g, Goal t, Conj t)+loadSentence _ prot g (L pos [S _ "forall", L _ vs, x]) =+ do+ (g, vars) <- loadVars g vs+ loadImplication pos prot g (L.nub $ reverse vars) x+loadSentence pos _ _ _ = fail (shows pos "Bad goal sentence")++-- Load the top-level implication of a security goal++loadImplication :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ g -> [t] -> SExpr Pos -> m (g, Goal t, Conj t)+loadImplication _ prot g vars (L pos [S _ "implies", a, c]) =+ do+ (g, antec) <- loadRoleSpecific pos prot g vars vars a+ (g, concl) <- loadConclusion pos prot g vars c+ let goal =+ Goal { uvars = vars,+ antec = map snd antec,+ concl = map (map snd) concl }+ return (g, goal, antec)+loadImplication pos _ _ _ _ = fail (shows pos "Bad goal implication")++-- The conclusion must be a disjunction. Each disjunct may introduce+-- existentially quantified variables.++loadConclusion :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ g -> [t] -> SExpr Pos -> m (g, [Conj t])+loadConclusion _ _ g _ (L _ [S _ "false"]) = return (g, [])+loadConclusion _ prot g vars (L pos (S _ "or" : xs)) =+ loadDisjuncts pos prot g vars xs []+loadConclusion pos prot g vars x =+ do+ (g, a) <- loadExistential pos prot g vars x+ return (g, [a])++loadDisjuncts :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ g -> [t] -> [SExpr Pos] -> [Conj t] -> m (g, [Conj t])+loadDisjuncts _ _ g _ [] rest = return (g, reverse rest)+loadDisjuncts pos prot g vars (x : xs) rest =+ do+ (g, a) <- loadExistential pos prot g vars x+ loadDisjuncts pos prot g vars xs (a : rest)++loadExistential :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ g -> [t] -> SExpr Pos -> m (g, Conj t)+loadExistential _ prot g vars (L pos [S _ "exists", L _ vs, x]) =+ do+ (g, evars) <- loadVars g vs+ loadRoleSpecific pos prot g (reverse evars ++ vars) evars x+loadExistential pos prot g vars x =+ loadRoleSpecific pos prot g vars [] x++--- Load a conjunction of atomic formulas and ensure the formula is+--- role specific.++loadRoleSpecific :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ g -> [t] -> [t] -> SExpr Pos -> m (g, Conj t)+loadRoleSpecific pos prot g vars unbound x =+ do+ (g, as) <- loadConjunction pos prot vars g x+ let as' = L.sortBy (\(_, x) (_, y) -> aFormOrder x y) as+ unbound <- foldM roleSpecific unbound as'+ case unbound of+ [] -> return (g, as')+ (v : _) -> fail (shows (annotation x) (showst v " not used"))++-- Load a conjunction of atomic formulas++loadConjunction :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ [t] -> g -> SExpr Pos -> m (g, Conj t)+loadConjunction _ p kvars g (L pos (S _ "and" : xs)) =+ loadConjuncts pos p kvars g xs []+loadConjunction top p kvars g x =+ do+ (g, pos, a) <- loadPrimary top p kvars g x+ return (g, [(pos, a)])++loadConjuncts :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ [t] -> g -> [SExpr Pos] -> Conj t -> m (g, Conj t)+loadConjuncts _ _ _ g [] rest = return (g, reverse rest)+loadConjuncts top p kvars g (x : xs) rest =+ do+ (g, pos, a) <- loadPrimary top p kvars g x+ loadConjuncts top p kvars g xs ((pos, a) : rest)++-- Load the atomic formulas++loadPrimary :: (Algebra t p g s e c, Monad m) => Pos -> Prot t g ->+ [t] -> g -> SExpr Pos -> m (g, Pos, AForm t)+loadPrimary _ _ kvars g (L pos [S _ "=", x, y]) =+ do+ (g, t) <- loadSgTerm kvars g x+ (g, t') <- loadSgTerm kvars g y+ return (g, pos, Equals t t')+loadPrimary _ _ kvars g (L pos [S _ "non", x]) =+ do+ t <- loadAlgTerm kvars x+ return (g, pos, Non t)+loadPrimary _ _ kvars g (L pos [S _ "pnon", x]) =+ do+ t <- loadAlgTerm kvars x+ return (g, pos, Pnon t)+loadPrimary _ _ kvars g (L pos [S _ "uniq", x]) =+ do+ t <- loadAlgTerm kvars x+ return (g, pos, Uniq t)+loadPrimary _ _ kvars g (L pos [S _ "uniq-at", x, y]) =+ do+ t <- loadAlgTerm kvars x+ (g, t') <- loadNodeTerm kvars g y+ return (g, pos, UniqAt t t')+loadPrimary _ _ kvars g (L pos [S _ "str-prec", x, y]) =+ do+ (g, t) <- loadNodeTerm kvars g x+ (g, t') <- loadNodeTerm kvars g y+ return (g, pos, StrPrec t t')+loadPrimary _ _ kvars g (L pos [S _ "prec", x, y]) =+ do+ (g, t) <- loadNodeTerm kvars g x+ (g, t') <- loadNodeTerm kvars g y+ return (g, pos, Prec t t')+loadPrimary _ p kvars g (L pos [S _ "p", Q _ name, N _ i, x]) =+ do+ r <- lookupRole pos p name+ (g, t) <- loadNodeTerm kvars g x+ case i < 0 || i >= length (rtrace r) of+ True -> fail (shows pos "Bad index")+ False -> return (g, pos, RolePred r i t)+loadPrimary _ p kvars g (L pos [S _ "p", Q _ name, Q var x, y, z]) =+ do+ r <- lookupRole pos p name+ v <- loadAlgTerm (rvars r) (S var x)+ (g, n) <- loadNodeTerm kvars g y+ t <- loadAlgTerm kvars z+ case isVar v of+ False -> fail (shows pos "Bad parameter -- not a variable")+ True -> return (g, pos, ParamPred r v n t)+loadPrimary _ _ _ _ (L pos (S _ "p" : Q _ name : _)) =+ fail (shows pos ("Bad role specific formula for role " ++ name))+loadPrimary _ _ _ _ (L pos (S _ pred : _)) =+ fail (shows pos ("Bad formula for predicate " ++ pred))+loadPrimary pos _ _ _ _ = fail (shows pos "Bad formula")++-- Load a term and make sure it has sort node++loadNodeTerm :: (Algebra t p g s e c, Monad m) => [t] -> g ->+ SExpr Pos -> m (g, t)+loadNodeTerm ts g x =+ do+ (g, t) <- loadSgTerm ts g x+ case isNodeVar t of+ True -> return (g, t)+ False -> fail (shows (annotation x) "Expecting a node variable")++-- Load a term and make sure it does not have sort node++loadAlgTerm :: (Algebra t p g s e c, Monad m) => [t] -> SExpr Pos -> m t+loadAlgTerm _ x@(L _ [N _ _, N _ _]) =+ fail (shows (annotation x) "Expecting an algebra term")+loadAlgTerm ts x =+ do+ t <- loadTerm ts x+ case isNodeVar t of+ True -> fail (shows (annotation x) "Expecting an algebra term")+ False -> return t++loadSgTerm :: (Algebra t p g s e c, Monad m) => [t] -> g ->+ SExpr Pos -> m (g, t)+loadSgTerm ts g x =+ do+ t <- loadTerm ts x+ return (g, t)++-- Role specific check++termVars :: Algebra t p g s e c => t -> [t]+termVars t = addVars [] t++allBound :: Algebra t p g s e c => [t] -> t -> Bool+allBound unbound t =+ L.all (flip L.notElem unbound) (termVars t)++-- Returns variables in unbound that are not role specific++roleSpecific :: (Algebra t p g s e c, Monad m) =>+ [t] -> (Pos, AForm t) -> m [t]+roleSpecific unbound (_, RolePred _ _ n) =+ return $ L.delete n unbound+roleSpecific unbound (pos, ParamPred _ _ n t)+ | L.notElem n unbound = return $ unbound L.\\ termVars t+ | otherwise = fail (shows pos "Unbound variable in parameter predicate")+roleSpecific unbound (pos, StrPrec n n')+ | L.notElem n unbound && L.notElem n' unbound = return unbound+ | otherwise = fail (shows pos "Unbound variable in str-prec")+roleSpecific unbound (pos, Prec n n')+ | L.notElem n unbound && L.notElem n' unbound = return unbound+ | otherwise = fail (shows pos "Unbound variable in prec")+roleSpecific unbound (pos, Non t)+ | allBound unbound t = return unbound+ | otherwise = fail (shows pos "Unbound variable in non")+roleSpecific unbound (pos, Pnon t)+ | allBound unbound t = return unbound+ | otherwise = fail (shows pos "Unbound variable in pnon")+roleSpecific unbound (pos, Uniq t)+ | allBound unbound t = return unbound+ | otherwise = fail (shows pos "Unbound variable in uniq")+roleSpecific unbound (pos, UniqAt t n)+ | allBound unbound t && L.notElem n unbound = return unbound+ | otherwise = fail (shows pos "Unbound variable in uniq-at")+roleSpecific unbound (pos, Equals t t')+ | isNodeVar t && isNodeVar t' =+ case L.notElem t unbound && L.notElem t' unbound of+ True -> return unbound+ False -> fail (shows pos "Unbound variable in equals")+ | isNodeVar t = fail (shows pos "Type mismatch in equals")+ | isNodeVar t' = fail (shows pos "Type mismatch in equals")+ | allBound unbound t && allBound unbound t' = return unbound+ | otherwise = fail (shows pos "Unbound variable in equals")
src/CPSA/Lib/Protocol.hs view
@@ -12,7 +12,7 @@ Role, rname, rvars, rtrace, rnon, rpnon, runique, rcomment, rsearch, rnorig, rpnorig, ruorig, rpriority, mkRole, varSubset, varsInTerms, addVars,- Prot, mkProt, pname, alg, pgen, roles,+ Prot, mkProt, pname, alg, pgen, roles, listenerRole, varsAllAtoms, pcomment, flow) where import qualified Data.List as L@@ -251,17 +251,18 @@ = Prot { pname :: !String, -- Name of the protocol alg :: !String, -- Name of the algebra pgen :: !g, -- Initial variable generator- roles :: ![Role t],+ roles :: ![Role t], -- Non-listener roles of a protocol+ listenerRole :: Role t, varsAllAtoms :: !Bool, -- Are all role variables atoms? pcomment :: [SExpr ()] } -- Comments from the input deriving Show -- Callers should ensure every role has a distinct name. mkProt :: Algebra t p g s e c => String -> String ->- g -> [Role t] -> [SExpr ()] -> Prot t g-mkProt name alg gen roles comment =- Prot { pname = name, alg = alg, pgen = gen,- roles = roles, pcomment = comment,+ g -> [Role t] -> Role t -> [SExpr ()] -> Prot t g+mkProt name alg gen roles lrole comment =+ Prot { pname = name, alg = alg, pgen = gen, roles = roles,+ listenerRole = lrole, pcomment = comment, varsAllAtoms = all roleVarsAllAtoms roles } where roleVarsAllAtoms role = all isAtom (rvars role)
src/CPSA/Lib/Reduction.hs view
@@ -18,6 +18,7 @@ import CPSA.Lib.SExpr import CPSA.Lib.Entry import CPSA.Lib.Algebra+import CPSA.Lib.Goal import CPSA.Lib.Strand import CPSA.Lib.Cohort import CPSA.Lib.Displayer@@ -340,6 +341,8 @@ (map (N ()) (L.sort (L.nub seen))) $ addKeyValues "unrealized" (map displayNode $ L.sort unrealized) $ condAddKeyValues "shape" shape [] $+ condAddKeyValues "satisfies" (shape && (not $ null $ kgoals k))+ (satisfies k) $ -- Structure preserving maps -- Added for cpsasas program condAddKeyValues "maps" shape (maps k) $@@ -375,6 +378,16 @@ rest maybeAddVKeyValues key f (Just x) rest = addKeyValues key (f x) rest++-- Variable assignments and security goals++satisfies :: Algebra t p g s e c => Preskel t g s e -> [SExpr ()]+satisfies k =+ map f (sat k) where+ f (_, []) = S () "yes"+ f (g, e : _) =+ L () (S () "no" : displayEnv (ctx $ uvars g) (ctx $ kvars k) e)+ ctx ts = addToContext emptyContext ts -- Prints structure preserving maps (homomorphisms) maps :: Algebra t p g s e c => Preskel t g s e -> [SExpr ()]
src/CPSA/Lib/Strand.hs view
@@ -8,14 +8,14 @@ module CPSA.Lib.Strand (Instance, mkInstance, bldInstance, mkListener, role, env, trace, height, listenerTerm, Sid, Node, mkPreskel,- firstSkeleton, Pair, Preskel, gen, protocol, insts, orderings,+ firstSkeleton, Pair, Preskel, gen, protocol, kgoals, insts, orderings, pov, knon, kpnon, kunique, korig, kpriority, kcomment, nstrands, kvars, strandids, kterms, uniqOrig, preskelWellFormed, verbosePreskelWellFormed, Strand, inst, sid, nodes, Vertex, strand, pos, preds, event, graphNode, strands, vertex, Gist, gist, isomorphic, contract, augment, inheritRnon, inheritRpnon, inheritRunique, addListener, Cause (..), Direction (..), Method (..), Operation (..), operation,- prob, homomorphism, toSkeleton, generalize, collapse) where+ prob, homomorphism, toSkeleton, generalize, collapse, sat) where import Control.Monad import qualified Data.List as L@@ -26,6 +26,7 @@ import CPSA.Lib.SExpr import CPSA.Lib.Algebra import CPSA.Lib.Protocol+import CPSA.Lib.Goal {-- import System.IO.Unsafe@@ -87,12 +88,6 @@ useSingleStrandThinning :: Bool useSingleStrandThinning = False -- True --- Enable de-origination.--- Don't use de-origination without thinning although you may want to--- use thinning without de-origination.-useDeOrigination :: Bool-useDeOrigination = False -- True- -- Sanity check: ensure no role variable occurs in a skeleton. useCheckVars :: Bool useCheckVars = False@@ -195,24 +190,12 @@ trace = trace, height = length trace } --- This is the only place a role is generated with an empty name.--- This is what marks a strand as a listener.-mkListener :: Algebra t p g s e c => g -> t ->+mkListener :: Algebra t p g s e c => Prot t g -> g -> t -> (g, Instance t e)-mkListener gen term =- (gen'', Instance { role = mkRole "" vars [In rterm, Out rterm]- [] [] [] [] [] False,- env = env,- trace = [In term, Out term],- height = 2 })- where- (gen', rterm) = clone gen term -- Make role term- vars = addVars [] rterm -- Collect vars in role term- (gen'', env) =- case match rterm term (gen', emptyEnv) of- (gen'', env) : _ -> (gen'', env)- [] -> error msg- msg = "Strand.mkListener: cannot generate an environment."+mkListener p gen term =+ case bldInstance (listenerRole p) [In term, Out term] gen of+ [x] -> x+ _ -> error "Strand.mkListener: Cannot build an instance of a listener" -- Add to set s the variables that are in the range of instance i addIvars :: Algebra t p g s e c => Set t -> Instance t e -> Set t@@ -355,11 +338,26 @@ | otherwise = inner (p : orderings) True pairs rest sameStrands (n0, n1) = strand n0 == strand n1 +-- Shared part of preskeletons++data Shared t g = Shared+ { prot :: Prot t g,+ goals :: [Goal t] }++instance (Show t, Show g) => Show (Shared t g) where+ showsPrec _ s = shows (prot s)++protocol :: Preskel t g s e -> Prot t g+protocol k = prot $ shared k++kgoals :: Preskel t g s e -> [Goal t]+kgoals k = goals $ shared k+ -- Preskeletons data Preskel t g s e = Preskel { gen :: !g,- protocol :: Prot t g,+ shared :: Shared t g, insts :: ![Instance t e], strands :: ![Strand t e], orderings :: ![Pair],@@ -428,14 +426,15 @@ -- Create a preskeleton. The point of view field is not filled in. -- This version is exported for use by the loader. This preskeleton -- must be consumed by firstSkeleton.-mkPreskel :: Algebra t p g s e c => g -> Prot t g ->+mkPreskel :: Algebra t p g s e c => g -> Prot t g -> [Goal t] -> [Instance t e] -> [Pair] -> [t] -> [t] -> [t] -> [(Node, Int)] -> [SExpr ()] -> Preskel t g s e-mkPreskel gen protocol insts orderings non pnon unique prio comment =+mkPreskel gen protocol gs insts orderings non pnon unique prio comment = k { kcomment = comment } where- k = newPreskel gen protocol insts orderings non pnon+ k = newPreskel gen shared insts orderings non pnon unique prio New prob Nothing+ shared = Shared { prot = protocol, goals = gs } prob = strandids k -- Fixed point on k is okay. -- Strand functions@@ -461,11 +460,11 @@ -- preds field of each instance in this function. The maybe uniquely -- originating term data is also filled in. This version is used -- within this module.-newPreskel :: Algebra t p g s e c => g -> Prot t g ->+newPreskel :: Algebra t p g s e c => g -> Shared t g -> [Instance t e] -> [Pair] -> [t] -> [t] -> [t] -> [(Node, Int)] -> Operation t s -> [Sid] -> Maybe (Preskel t g s e) -> Preskel t g s e-newPreskel gen protocol insts orderings non pnon unique prio oper prob pov =+newPreskel gen shared insts orderings non pnon unique prio oper prob pov = let orderings' = L.nub orderings unique' = L.nub unique g = graph trace height insts orderings'@@ -474,7 +473,7 @@ orig = map (originationNodes strands) unique' tc = filter pairWellOrdered (graphClose $ graphEdges strands) k = Preskel { gen = gen,- protocol = protocol,+ shared = shared, insts = insts, strands = strands, orderings = orderings',@@ -860,7 +859,7 @@ let pnon' = map (substitute subst) (kpnon k) let unique' = map (substitute subst) (kunique k) let operation' = substOper subst (operation k)- let k' = newPreskel gen' (protocol k) insts'+ let k' = newPreskel gen' (shared k) insts' (orderings k) non' pnon' unique' (kpriority k) operation' (prob k) (pov k) k' <- wellFormedPreskel k'@@ -911,7 +910,7 @@ let k' = newPreskel (gen k)- (protocol k)+ (shared k) (deleteNth s (insts k)) orderings' (knon k)@@ -971,7 +970,7 @@ let k' = newPreskel (gen k)- (protocol k)+ (shared k) (deleteNth s (insts k)) orderings' (knon k)@@ -1000,8 +999,6 @@ skeletonize :: Algebra t p g s e c => Bool -> PRS t p g s e c -> [PRS t p g s e c] skeletonize thin prs- | useDeOrigination = hull thin prs- -- Cull preskels with a unique origination assumption that is not unique | hasMultipleOrig prs = [] -- Usual case | otherwise = enrich thin prs @@ -1018,30 +1015,14 @@ -- No uniques originate on more than one strand loop [] = enrich thin prs -- Found a pair that needs hulling- loop ((u, (s, i) : (s', i') : _) : _) =- hullByDeOrigination thin prs u (s, i) (s', i')+ loop ((_, (s, _) : (s', _) : _) : _) =+ do+ (s'', s''', subst) <- unifyStrands (skel prs) s s'+ prs <- ksubst prs subst+ prs' <- compress False prs s'' s'''+ hull thin prs' loop(_ : orig) = loop orig --- De-Origination--hullByDeOrigination :: Algebra t p g s e c => Bool -> PRS t p g s e c ->- t -> Node -> Node -> [PRS t p g s e c]-hullByDeOrigination thin prs u (s, i) (s', i') =- do- subst <- deOrig (skel prs) u (s, i) ++ deOrig (skel prs) u (s', i')- prs <- ksubst prs subst- hull thin prs--deOrig :: Algebra t p g s e c => Preskel t g s e -> t -> Node -> [(g, s)]-deOrig k u (s, i) =- [ (g, s) |- let tr = trace $ strandInst k s,- e <- take i tr,- t <- M.maybeToList $ inbnd e,- subterm <- S.toList $ foldCarriedTerms (flip S.insert) S.empty t,- (g, s) <- unify u subterm (gen k, emptySubst),- not $ originates (substitute s u) (map (evtMap $ substitute s) tr) ]- -- Order Enrichment -- Adds orderings so that a skeleton respects origination.@@ -1057,7 +1038,7 @@ let k' = newPreskel (gen k)- (protocol k)+ (shared k) (insts k) o (knon k)@@ -1313,7 +1294,7 @@ let k' = newPreskel (gen k)- (protocol k)+ (shared k) (insts k) o (knon k)@@ -1358,7 +1339,7 @@ [Preskel t g s e] toSkeleton thin k = do- prs <- skeletonize thin (k, k, (0, 0), strandids k, emptySubst)+ prs <- hull thin (k, k, (0, 0), strandids k, emptySubst) (k', _, _, _) <- homomorphismFilter prs return k' @@ -1419,7 +1400,7 @@ let non' = inheritRnon inst ++ (knon k) let pnon' = inheritRpnon inst ++ (kpnon k) let unique' = inheritRunique inst ++ (kunique k)- let k' = newPreskel (gen k) (protocol k) insts'+ let k' = newPreskel (gen k) (shared k) insts' orderings' non' pnon' unique' (kpriority k) (operation k) (prob k) (pov k) k' <- wellFormedPreskel k'@@ -1511,10 +1492,10 @@ (k, k', n, strandids k, emptySubst) homomorphismFilter prs where- k' = newPreskel gen' (protocol k) insts' orderings' (knon k)+ k' = newPreskel gen' (shared k) insts' orderings' (knon k) (kpnon k) (kunique k) (kpriority k) (AddedListener t cause) (prob k) (pov k)- (gen', inst) = mkListener (gen k) t+ (gen', inst) = mkListener (protocol k) (gen k) t insts' = insts k ++ [inst] pair = ((length (insts k), 1), n) orderings' = pair : orderings k@@ -1660,7 +1641,7 @@ g -> Node -> [Instance t e] -> [Pair] -> [Sid] -> Preskel t g s e deleteNodeRest k gen n insts' orderings prob =- newPreskel gen (protocol k) insts' orderings non' pnon' unique'+ newPreskel gen (shared k) insts' orderings non' pnon' unique' prio' (Generalized (Deleted n)) prob (pov k) where -- Drop nons that aren't mentioned anywhere@@ -1703,7 +1684,7 @@ weaken k p orderings = addIdentity k' where- k' = newPreskel (gen k) (protocol k) (insts k)+ k' = newPreskel (gen k) (shared k) (insts k) orderings (knon k) (kpnon k) (kunique k) (kpriority k) (Generalized (Weakened p)) (prob k) (pov k) @@ -1862,9 +1843,9 @@ changeLocations k env gen t locs = [addIdentity k0, addIdentity k1] where- k0 = newPreskel gen' (protocol k) insts' (orderings k) non pnon unique0+ k0 = newPreskel gen' (shared k) insts' (orderings k) non pnon unique0 (kpriority k) (Generalized (Separated t)) (prob k) (pov k)- k1 = newPreskel gen' (protocol k) insts' (orderings k) non pnon unique1+ k1 = newPreskel gen' (shared k) insts' (orderings k) non pnon unique1 (kpriority k) (Generalized (Separated t)) (prob k) (pov k) (gen', insts') = changeStrands locs t gen (strands k) non = knon k ++ map (instantiate env) (knon k)@@ -1932,3 +1913,176 @@ prs <- compress True prs s s' prs <- skeletonize useThinningDuringCollapsing prs return $ skel prs++-- Security goals: satisfaction of atomic formulas++type Sem t g s e = Preskel t g s e -> (g, e) -> [(g, e)]++-- Extends an environment (a variable assignment) according to the+-- given atomic formula.+satisfy :: Algebra t p g s e c => AForm t -> Sem t g s e+satisfy (Equals t t') = geq t t'+satisfy (Non t) = ggnon t+satisfy (Pnon t) = ggpnon t+satisfy (Uniq t) = gguniq t+satisfy (UniqAt t n) = guniqAt t n+satisfy (StrPrec n n') = gstrPrec n n'+satisfy (Prec n n') = gprec n n'+satisfy (RolePred r i n) = grole r i n+satisfy (ParamPred r v n t) = gparam r v n t++-- Equality This isn't right. Suppose t is a compound term which has+-- some unbound variable. Need static role specific check to+-- eliminate this case.+geq :: Algebra t p g s e c => t -> t -> Sem t g s e+geq t t' _ (g, e)+ | t == ti = error ("Strand.geq: " ++ show t ++ " unbound")+ | t' == ti' = error ("Strand.geq: " ++ show t' ++ " unbound")+ | ti == ti' = [(g, e)]+ | otherwise = []+ where+ ti = instantiate e t+ ti' = instantiate e t'++-- Non-origination+ggnon :: Algebra t p g s e c => t -> Sem t g s e+ggnon t k e =+ do+ t' <- knon k+ match t t' e++-- Penetrator non-origination+ggpnon :: Algebra t p g s e c => t -> Sem t g s e+ggpnon t k e =+ do+ t' <- kpnon k+ match t t' e++-- Unique origination+gguniq :: Algebra t p g s e c => t -> Sem t g s e+gguniq t k e =+ do+ t' <- kunique k+ match t t' e++-- Unique origination at a node+guniqAt :: Algebra t p g s e c => t -> t -> Sem t g s e+guniqAt t n k e =+ do+ (t', ls) <- korig k+ case ls of+ [l] ->+ do+ e <- match t t' e+ nodeMatch n l e+ _ -> []++inSkel :: Algebra t p g s e c => Preskel t g s e -> (Int, Int) -> Bool+inSkel k (s, i) =+ s >= 0 && s < nstrands k && i >= 0 && i < height (insts k !! s)++strandPrec :: Node -> Node -> Bool+strandPrec (s, i) (s', i')+ | s == s' && i < i' = True+ | otherwise = False++-- Within strand node precedes+gstrPrec :: Algebra t p g s e c => t -> t -> Sem t g s e+gstrPrec n n' k (g, e) =+ case (nodeLookup e n, nodeLookup e n') of+ (Just p, Just p')+ | inSkel k p && inSkel k p' && strandPrec p p' -> [(g, e)]+ (Just _, Just _) -> []+ (_, Just _) ->+ error ("Strand.gstrPrec: node " ++ show n ++ " unbound")+ _ ->+ error ("Strand.gstrPrec: node " ++ show n' ++ " unbound")++-- Node precedes+-- This should look at the transitive closure of the ordering graph.+gprec :: Algebra t p g s e c => t -> t -> Sem t g s e+gprec n n' k (g, e) =+ case (nodeLookup e n, nodeLookup e n') of+ (Just p, Just p')+ | inSkel k p && inSkel k p' && + (strandPrec p p' || elem (p, p') tc) -> [(g, e)]+ (Just _, Just _) -> []+ (_, Just _) ->+ error ("Strand.gstrPrec: node " ++ show n ++ " unbound")+ _ ->+ error ("Strand.gstrPrec: node " ++ show n' ++ " unbound")+ where+ tc = map graphPair $ graphClose $ graphEdges $ strands k++-- Role predicate+-- r and i determine the predicate, which has arity one.+grole :: Algebra t p g s e c => Role t -> Int -> t -> Sem t g s e+grole r i n k (g, e) =+ case nodeLookup e n of+ Nothing ->+ do+ (z, inst) <- zip [0..] $ insts k+ case () of+ _ | i >= height inst -> []+ | rname (role inst) == rname r -> nodeMatch n (z, i) (g, e)+ | otherwise -> -- See if z could have been an instance of r+ case bldInstance r (take (i + 1) $ trace inst) g of+ [] -> []+ _ -> nodeMatch n (z, i) (g, e)+ Just (z, j) | z < nstrands k && i == j ->+ let inst = insts k !! z in+ case () of+ _ | i >= height inst -> []+ | rname (role inst) == rname r -> [(g, e)]+ | otherwise ->+ case bldInstance r (take (i + 1) $ trace inst) g of+ [] -> []+ _ -> [(g, e)]+ _ -> []++-- Parameter predicate++-- r and t determine the predicate, which has arity two. t must be+-- a variable declared in role r.+gparam :: Algebra t p g s e c => Role t -> t -> t -> t -> Sem t g s e+gparam r t n t' k (g, e) =+ case nodeLookup e n of+ Just (z, i) | z < nstrands k ->+ let inst = insts k !! z in+ case () of+ _ | i >= height inst -> []+ | rname (role inst) == rname r ->+ match t' (instantiate (env inst) t) (g, e)+ | otherwise ->+ do+ (g, inst) <- bldInstance r (take (i + 1) $ trace inst) g+ match t' (instantiate (env inst) t) (g, e)+ Nothing -> error ("Strand.gparam: node " ++ show n ++ " unbound")+ _ -> []++-- Conjunction++conjoin :: Algebra t p g s e c => [AForm t] -> Sem t g s e+conjoin [] _ e = [e]+conjoin (a: as) k e =+ do+ e <- satisfy a k e+ conjoin as k e++-- Satisfaction++-- Returns the environments that show satifaction of the antecedent+-- but fail to be extendable to show satifaction of one of the+-- conclusions.+goalSat :: Algebra t p g s e c => Preskel t g s e -> Goal t -> (Goal t, [e])+goalSat k g =+ (g, [ e |+ (gen, e) <- conjoin (antec g) k (gen k, emptyEnv),+ conclusion (gen, e) ])+ where+ conclusion e = all (disjunct e) $ concl g+ disjunct e a = null $ conjoin a k e++sat :: Algebra t p g s e c => Preskel t g s e -> [(Goal t, [e])]+sat k =+ map (goalSat k) (kgoals k)
src/CPSA/SAS/SAS.hs view
@@ -48,9 +48,7 @@ k <- loadPreskel pos p (pgen p) xs case (isSkeleton k, isShape k) of (True, False) ->- do -- Found POV- origCheck pos k -- Ensure uniqs originate- return ((ps, [k]), Nothing)+ return ((ps, [k]), Nothing) -- Found POV _ -> return ((ps, []), Nothing) -- Not POV loadPOV _ _ ps _ = return ((ps, []), Nothing) @@ -67,26 +65,10 @@ let g = kgen (last ks) -- Make sure vars in skeleton are k <- loadPreskel pos p g xs -- distinct from the ones in the POV case isShape k of- True ->- do -- Found shape- origCheck pos k -- Ensure uniqs originate- return ((ps, k : ks), Nothing)+ True -> return ((ps, k : ks), Nothing) -- Found shape False -> return ((ps, ks), Nothing) -- Found intermediate skeleton loadOtherPreskel _ _ ps ks _ = return ((ps, ks), Nothing) --- Ensure every uniq originates-origCheck :: (Algebra t p g s e c, Monad m) =>- Pos -> Preskel t g c -> m ()-origCheck pos k =- mapM_ f (uniqs k)- where- f t | any (\(t', _) -> t == t') (origs k) = return ()- | otherwise =- fail (shows pos "Uniq " ++ u ++ " has no origination point")- where- u = pp 0 0 (displayTerm ctx t)- ctx = addToContext emptyContext (kvars k)- -- Load a protocol -- The Prot record contains information extraced from protocols for@@ -248,6 +230,7 @@ orderings :: [(t, t)], succs :: [(t, t)], nons :: [t],+ pnons :: [t], uniqs :: [t], origs :: [(t, t)], isSkeleton :: Bool,@@ -264,6 +247,7 @@ let heights = map height insts orderings <- loadOrderings heights (assoc precedesKey xs) nons <- loadBaseTerms kvars (assoc nonOrigKey xs)+ pnons <- loadBaseTerms kvars (assoc pnonOrigKey xs) uniqs <- loadBaseTerms kvars (assoc uniqOrigKey xs) origs <- loadOrigs kvars heights (assoc origsKey xs) let strands = map (\(s, h) -> (s, h - 1)) (zip [0..] heights)@@ -279,6 +263,7 @@ orderings = map f orderings, succs = loadSuccs varmap, nons = nons,+ pnons = pnons, uniqs = uniqs, origs = map g origs, isSkeleton = not $ hasKey preskeletonKey xs,@@ -516,6 +501,10 @@ nonOrigKey :: String nonOrigKey = "non-orig" +-- The key used in preskeletons for penetrator non-originating atoms+pnonOrigKey :: String+pnonOrigKey = "pen-non-orig"+ -- The key used in preskeletons for uniquely originating atoms uniqOrigKey :: String uniqOrigKey = "uniq-orig"@@ -601,6 +590,7 @@ orderings = mapPair (instantiate env) (orderings k), succs = mapPair (instantiate env) (succs k), nons = map (instantiate env) (nons k),+ pnons = map (instantiate env) (pnons k), uniqs = map (instantiate env) (uniqs k), origs = mapPair (instantiate env) (origs k), varmap = M.map (instantiate env) (varmap k) }@@ -625,7 +615,8 @@ form (pov, shapes) = let (c, vars, conj) = skel emptyContext pov in let disj = map (shape c conj) shapes in- quantify "forall" vars (imply (conjoin conj) (disjoin disj))+ L () [S () "defgoal", S () (pname $ protocol pov), -- Name of protocol+ quantify "forall" vars (imply (conjoin conj) (disjoin disj))] -- Convert one skeleton into a declaration and a conjunction. The -- declaration is used as the bound variables in a quantifier. The@@ -640,11 +631,13 @@ (kctx, displayVars kctx (kvars k) ++ listMap node nodes, map (nodeForm kctx k) (M.assocs (varmap k)) ++- map (strandForm kctx k) (zip (strands k) $ insts k) +++ map (strandForm kctx) (zip (strands k) $ insts k) ++ map (precForm kctx) (orderings k) ++ map (sprecForm kctx) (succs k) ++ map (unary "non" kctx) (nons k) ++- map (uniqForm kctx) (origs k))+ map (unary "pnon" kctx) (pnons k) +++ map (unary "uniq" kctx) (noOrigUniqs k) +++ map (uniqAtForm kctx) (origs k)) -- map through lists in an S-Expression. listMap :: ([SExpr ()] -> [SExpr ()]) -> [SExpr ()] -> [SExpr ()]@@ -663,7 +656,6 @@ (Node, t) -> SExpr () nodeForm c k ((s, i), n) = L () [S () "p",- Q () $ pname $ protocol k, -- Name of the protocol Q () $ rname $ role inst, -- Name of the role N () $ i, displayTerm c n]@@ -675,14 +667,12 @@ quote x = x -- Creates the atomic formulas used to describe an instance of a role-strandForm :: Algebra t p g s e c => c -> Preskel t g c ->- (t, Instance t c) -> SExpr ()-strandForm c k (s, inst) =+strandForm :: Algebra t p g s e c => c -> (t, Instance t c) -> SExpr ()+strandForm c (s, inst) = conjoin (map f (env inst)) where f (x, t) = L () [S () "p",- Q () $ pname $ protocol k, -- Name of the protocol Q () $ rname $ role inst, -- Name of the role quote $ displayTerm (ctx $ role inst) x, displayTerm c s,@@ -694,11 +684,18 @@ -- Creates the atomic formula used to describe a strand node ordering sprecForm :: Algebra t p g s e c => c -> (t, t) -> SExpr ()-sprecForm = binary "sprec"+sprecForm = binary "str-prec" -uniqForm :: Algebra t p g s e c => c -> (t, t) -> SExpr ()-uniqForm = binary "uniq"+uniqAtForm :: Algebra t p g s e c => c -> (t, t) -> SExpr ()+uniqAtForm = binary "uniq-at" +-- Returns the uniqs that do not originate in k.+noOrigUniqs :: Algebra t p g s e c => Preskel t g c -> [t]+noOrigUniqs k =+ [ t | t <- uniqs k, all (f t) (origs k) ]+ where+ f t (t', _) = t /= t'+ -- Creates a formula associated with a shape. It is a disjunction of -- existentially quantified formulas that describe the homomorphism -- and the shape as a skeleton.@@ -711,7 +708,7 @@ quantify "exists" vars (conjoin (n ++ a ++ (conj L.\\ pov))) displayEq :: Algebra t p g s e c => c -> (t, t) -> SExpr ()-displayEq = binary "equal"+displayEq = binary "=" -- Formula primitives
− src/cpsaextras/Main.scala
@@ -1,47 +0,0 @@-package cpsaextras--import java.io._-import java.util.ResourceBundle;--object Main {-- /**- * @param args the command line arguments- */- def main(args: Array[String]): Unit = {- if (args.length != 1) {- println("Usage: cpsaextras INPUT")- println(getVersion())- }- else {- val in = new BufferedReader(new FileReader(args(0)))- val sr = new SExprReader(args(0), in)- val out = new PrintWriter(System.out)- while (true) {- val x = sr.read()- if (x == null) {- out.close()- return- }- Printer.pp(out, 80, 2, x)- out.println()- out.println()- }- }- }-- private var resources: ResourceBundle = null-- private val VERSION_RESOURCES = "cpsaextras/version"-- /**- * Get program name and a version number from a resource.- */- def getVersion() = {- if (resources == null)- resources = ResourceBundle.getBundle(VERSION_RESOURCES)- val program = resources.getString("program")- val version = resources.getString("version")- program + " " + version- }-}
− src/cpsaextras/Pretty.scala
@@ -1,159 +0,0 @@-/*- * A simple pretty printer- *- * The alogithm is by Lawrence C. Paulson, who simplified an algorithm- * by Derek C. Oppen.- *- * Derek C. Oppen, Prettyprinting, ACM Transactions on Programming- * Languages and Systems, Vol 2, No. 4, October 1980, Pages 465-483.- *- * Copyright (c) 2010 The MITRE Corporation- *- * This program is free software: you can redistribute it and/or modify- * it under the terms of the BSD License as published by the University- * of California.- */--/* A pretty printer based on ML programs with the following copyright--(**** ML Programs from Chapter 8 of-- ML for the Working Programmer, 2nd edition- by Lawrence C. Paulson, Computer Laboratory, University of Cambridge.- (Cambridge University Press, 1996)--Copyright (C) 1996 by Cambridge University Press.-Permission to copy without fee is granted provided that this copyright-notice and the DISCLAIMER OF WARRANTY are included in any copy.--DISCLAIMER OF WARRANTY. These programs are provided `as is' without-warranty of any kind. We make no warranties, express or implied, that the-programs are free of error, or are consistent with any particular standard-of merchantability, or that they will meet your requirements for any-particular application. They should not be relied upon for solving a-problem whose incorrect solution could result in injury to a person or loss-of property. If you do use the programs or functions in such a manner, it-is at your own risk. The author and publisher disclaim all liability for-direct, incidental or consequential damages resulting from your use of-these programs or functions.-****)--*/--package cpsaextras--import java.io.PrintWriter--/** Abstract data type for pretty printing. */-sealed abstract class Pretty-private case class Str(s: String) extends Pretty-private case class Brk(n: Int) extends Pretty-private case class Blo(l: List[Pretty], indent: Int, n: Int) extends Pretty-private case class Grp(l: List[Pretty], indent: Int, n: Int) extends Pretty--object Pretty {- // Exported constructors-- /** Create a string.- * @param s string to be printed- */- def str(s: String): Pretty = {- Str(s)- }-- /** Create a break point.- * @param n number of spaces- */- def brk(n: Int): Pretty = {- Brk(n)- }-- /** Create an indentation block. When pretty printing, any of the- * break points in the list can be used.- * @param indent number of spaces to indent- * @param es a list that includes break points- */- def blo(indent: Int, es: List[Pretty]): Pretty = {- Blo(es, indent, len(es, 0))- }-- /** Create an indentation group. When pretty printing,- * either all or none of the break points are used.- * @param indent number of spaces to indent- * @param es a list that includes break points- */- def grp(indent: Int, es: List[Pretty]): Pretty = {- Grp(es, indent, len(es, 0))- }-- private def len(es: List[Pretty], n: Int): Int = {- es match {- case Nil => n- case e :: es => len(es, size(e) + n)- }- }-- private def size(e: Pretty): Int = {- e match {- case Str(s) => s.length- case Brk(n) => n- case Blo(_, _, n) => n- case Grp(_, _, n) => n- }- }-- /** Print an object of type Pretty. */- def pr(w: PrintWriter, margin: Int, e: Pretty): Unit = {- printing(w, margin, List(e), margin, 0, false, margin)- }-- private def printing(w: PrintWriter, margin: Int, es: List[Pretty],- blockspace:Int, after: Int, force: Boolean,- space: Int): Int = {- es match {- case Nil => space- case e :: es =>- val space1 = e match {- case Str(s) => // Place a string- w.print(s)- space - s.length- case Brk(n) => // Place breakable space- if (!force && n + breakdist(es, after) <= space)- blanks(w, n, space) // Don't break- else {- w.println() // Break- blanks(w, margin - blockspace, margin)- }- case Blo(bes, indent, _) => // Place a block- printing(w, margin, bes, space - indent,- breakdist(es, after), false, space)- case Grp(bes, indent, n) => // Place a group- val dist = breakdist(es, after)- printing(w, margin, bes, space - indent,- dist, n + dist > space, space)- }- printing(w, margin, es, blockspace, after, force, space1)- }- }-- // Find the distance to the nearest breakable space- private def breakdist(es: List[Pretty], after: Int): Int = {- es match {- case Nil => after- case Str(s) :: es => s.length + breakdist(es, after)- case Brk(_) :: es => 0- case Blo(_, _, n) :: es => n + breakdist(es, after)- case Grp(_, _, n) :: es => n + breakdist(es, after)- }- }-- // Place spaces- private def blanks(w: PrintWriter, n: Int, space: Int): Int = {- if (n <= 0)- space- else {- w.print(' ')- blanks(w, n - 1, space - 1)- }- }-}
− src/cpsaextras/Printer.scala
@@ -1,122 +0,0 @@-/*- * A CPSA specific pretty printer- *- * Copyright (c) 2009 The MITRE Corporation- *- * This program is free software: you can redistribute it and/or- * modify it under the terms of the BSD License as published by the- * University of California.- */--package cpsaextras--import java.io.PrintWriter--object Printer {-- /** CPSA specific pretty printer.- * The pretty printer that indents a constant amount for each list. The- * top-level lists are laid out specially. Whenever some breaks- * occur, all breaks are forced. Also, breaks are only placed before- * strings and lists. CPSA protocols are handled specially. Each- * defrole is handled as are top-level lists.- *- * @param w the output writer- * @param margin the width to be filled- * @param indent the number of spaces in an indent- * @param x the S-expression to be pretty printed- */- def pp[A](w: PrintWriter, margin: Int, indent: Int, x: SExpr[A]): Unit = {- Pretty.pr(w, margin, pretty(indent, x))- }-- private def pretty[A](indent: Int, x: SExpr[A]): Pretty = {- x match {- case L(_, (x@S(_, "defprotocol")) :: xs) =>- roles(indent, xs, List(block(indent, x), Pretty.str("(")))- case x@L(_, S(_, "defmacro") :: _) =>- block(indent, x)- case x@L(_, S(_, "herald") :: _) =>- block(indent, x)- case _ =>- group(indent, x)- }- }-- // Role specific pretty printer- private def roles[A](indent: Int, xs: List[SExpr[A]],- acc: List[Pretty]): Pretty = {- xs match {- case Nil =>- Pretty.grp(indent, (Pretty.str(")") :: acc).reverse)- case (x@S(_, _)) :: xs =>- roles(indent, xs, block(indent, x) :: Pretty.str(" ") :: acc)- case (x@Q(_, _)) :: xs =>- roles(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)- case (x@N(_, _)) :: xs =>- roles(indent, xs, block(indent, x) :: Pretty.str(" ") :: acc)- case (x@L(_, S(_, "defrole") :: _)) :: xs =>- roles(indent, xs, group(indent, x) :: Pretty.brk(1) :: acc)- case (x@L(_, _)) :: xs =>- roles(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)- }- }-- // A pretty printer for top-level S-expressions- private def group[A](indent: Int, x: SExpr[A]): Pretty = {- x match {- case L(a, l) => grouplist(indent, l)- case _ => block(indent, x)- }- }-- private def grouplist[A](indent: Int, xs: List[SExpr[A]]): Pretty = {- xs match {- case Nil => Pretty.str("()")- case x :: xs =>- grouprest(indent, xs, List(block(indent, x), Pretty.str("(")))- }- }-- private def grouprest[A](indent: Int, xs: List[SExpr[A]],- acc: List[Pretty]): Pretty = {- xs match {- case Nil =>- Pretty.grp(indent, (Pretty.str(")") :: acc).reverse)- case (x@S(_, _)) :: xs =>- grouprest(indent, xs, block(indent, x) :: Pretty.str(" ") :: acc)- case (x@Q(_, _)) :: xs =>- grouprest(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)- case (x@N(_, _)) :: xs =>- grouprest(indent, xs, block(indent, x) :: Pretty.str(" ") :: acc)- case (x@L(_, _)) :: xs =>- grouprest(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)- }- }-- // A pretty printer for interior lists using block style breaking.- private def block[A](indent: Int, x: SExpr[A]): Pretty = {- x match {- case L(a, l) => blocklist(indent, l)- case _ => Pretty.str(x.toString())- }- }-- private def blocklist[A](indent: Int, xs: List[SExpr[A]]): Pretty = {- xs match {- case Nil => Pretty.str("()")- case x :: xs =>- blockrest(indent, xs, List(block(indent, x), Pretty.str("(")))- }- }-- private def blockrest[A](indent: Int, xs: List[SExpr[A]],- acc: List[Pretty]): Pretty = {- xs match {- case Nil =>- Pretty.blo(indent, (Pretty.str(")") :: acc).reverse)- case x :: xs =>- blockrest(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)- }- }-}
− src/cpsaextras/SExpr.scala
@@ -1,282 +0,0 @@-/*- * S-expressions- *-'* Copyright (c) 2010 The MITRE Corporation- *- * This program is free software: you can redistribute it and/or modify- * it under the terms of the BSD License as published by the University- * of California.- */--package cpsaextras--import java.io._--/**- * Annotated S-expressions. Each S-expression can be annotated with- * something of type A.- */-sealed abstract class SExpr[A] {- /** The annotation. */- val a: A-}-/** Case of a symbol. */-case class S[A](a: A, s: String) extends SExpr[A] {- override def toString(): String = {- s.toString()- }-}-/** Case of a string. */-case class Q[A](a: A, q: String) extends SExpr[A] {- override def toString(): String = {- "\"" + q.toString() + "\""- }-}-/** Case of a number. */-case class N[A](a: A, n: Int) extends SExpr[A] {- override def toString(): String = {- n.toString()- }-}-/** Case of a list of S-expressions. */-case class L[A](a: A, l: List[SExpr[A]]) extends SExpr[A] {- override def toString(): String = {- l.toString()- }-}--/** The file position annotation. */-final case class Pos(file: String, line: Int, column: Int) {- override def toString (): String = {- file + ":" + line + ":" + column + ": "- }-}--/** An S-expression reader.- *- * @param file name of the input file- * @param in stream associated with the input file- */-class SExprReader(file: String, in: Reader) {- private var line = 1 // Stream line number- private var column = 1 // Stream column-- // A scanner token- private sealed abstract class Token- // A token for a non-list S-expression- private case class Atom(a: SExpr[Pos]) extends Token- // A token for the left parenthesis- private case class LParen(p: Pos) extends Token- // A token for the right parenthesis- private case class RParen(p: Pos) extends Token- // A token for end-of-file- private case object Eof extends Token-- /**- * Reads an S-expression annotated with file positions.- * @return an S-expression or null on end-of-file- */- def read(): SExpr[Pos] = {- scan() match {- case Atom(a) => a- case LParen(p) => list(p, Nil)- case RParen(p) =>- in.close()- throw new IOException(p + "Close of unopened list")- case Eof =>- in.close()- null- }- }-- // Parse a non top-level list- private def list(pos: Pos, acc: List[SExpr[Pos]]): SExpr[Pos] = {- scan() match {- case Atom(a) => list(pos, a :: acc)- case LParen(p) => list(pos, list(p, Nil) :: acc)- case RParen(_) => L(pos, acc.reverse)- case Eof =>- in.close()- throw new IOException(pos + "Unexpected end of input in list")- }- }-- // Scanner-- // Consume white space and then dispatch on the first character- private def scan(): Token = {- val ch = get()- if (Character.isWhitespace(ch))- scan()- else ch match {- case -1 => Eof- case '(' => LParen(Pos(file, line, column))- case ')' => RParen(Pos(file, line, column))- case ';' => comment()- case _ => atom(ch)- }- }-- // Consume a comment and then resume scanning- private def comment(): Token = {- get() match {- case -1 => Eof- case '\n' => scan()- case _ => comment()- }- }-- // Scan an atom- private def atom(ch: Int): Token = {- val p = Pos(file, line, column) // Position of atom- ch match {- case '"' => string(p, new StringBuilder())- case '+' => numOrSym(p, singleton(ch))- case '-' => numOrSym(p, singleton(ch))- case _ =>- if (Character.isDigit(ch))- number(p, singleton(ch))- else if (isSym(ch))- symbol(p, singleton(ch))- else {- in.close()- throw new IOException(p + "Bad char in atom")- }- }- }-- // Create a string buffer with one character- private def singleton(ch: Int): StringBuilder = {- val sb = new StringBuilder()- sb.append(ch.toChar)- sb- }-- // Scan a string atom- private def string(p: Pos, sb: StringBuilder): Token = {- val ch = get()- if (ch == -1) {- in.close()- throw new IOException(p + "End of input in string")- }- else if (ch == '"')- Atom(Q(p, sb.toString().intern()))- else if (isStr(ch)) {- sb.append(ch.toChar)- string(p, sb)- }- else {- in.close()- throw new IOException(p + "Bad char for string")- }- }-- // Scan a number atom- private def number(p: Pos, sb: StringBuilder): Token = {- val ch = peek()- if (ch == -1)- Atom(N(p, Integer.parseInt(sb.toString())))- else if (Character.isDigit(ch)) {- get()- sb.append(ch.toChar)- number(p, sb)- }- else if (isSym(ch)) {- in.close()- throw new IOException(p + "Bad char after number")- }- else- Atom(N(p, Integer.parseInt(sb.toString())))- }-- // See if an atom is an number or a symbol- private def numOrSym(p: Pos, sb: StringBuilder): Token = {- val ch = peek()- if (ch == -1)- symbol(p, sb)- else if (Character.isDigit(ch))- number(p, sb)- else- symbol(p, sb)- }-- // Scan a symbol- private def symbol(p: Pos, sb: StringBuilder): Token = {- val ch = peek()- if (ch == -1)- Atom(S(p, sb.toString().intern()))- else if (isSym(ch)) {- get()- sb.append(ch.toChar)- symbol(p, sb)- }- else- Atom(S(p, sb.toString().intern()))- }-- // Is character a constituent of a symbol?- private def isSym(ch: Int) = {- ch match {- case '+' => true- case '-' => true- case '*' => true- case '/' => true- case '<' => true- case '=' => true- case '>' => true- case '!' => true- case '?' => true- case ':' => true- case '$' => true- case '%' => true- case '_' => true- case '&' => true- case '~' => true- case '^' => true- case _ => Character.isLetterOrDigit(ch)- }- }-- // Is character a constituent of a string?- private def isStr(ch: Int) = {- ch match {- case '"' => false- case '\\' => false- case _ => !Character.isISOControl(ch)- }- }-- // Character reader with look ahead-- private var peeked = false // Is look ahead active?- private var seen = 0 // peeked character-- // Get next character and set the current file position.- private def get(): Int = {- val next =- if (peeked) {- peeked = false- seen- }- else- in.read()- if (next == '\n') {- line += 1- column = 1- }- else- column += 1- next- }-- // Read ahead if need be- private def peek(): Int = {- if (peeked)- seen- else {- peeked = true- seen = in.read()- seen- }- }-}
src/prover9.pl view
@@ -7,6 +7,15 @@ %% Known to work in SWI-Prolog, but not with GNU Prolog. +%% To handle the subsort relations of the message algebra, add the+%% following axioms.++%% all T (akey(T) -> mesg(T)).+%% all T (skey(T) -> mesg(T)).+%% all T (name(T) -> mesg(T)).+%% all T (text(T) -> mesg(T)).+%% all T (name(T) -> mesg(T)).+ %% Copyright (c) 2011 The MITRE Corporation %% %% This program is free software: you can redistribute it and/or@@ -28,7 +37,7 @@ %% Ignore all forms except the ones that start with forall. top_forms_pp(_, []).-top_forms_pp(Out, [[forall|Rest]|Forms]) :-+top_forms_pp(Out, [[defsas, _, [forall|Rest]]|Forms]) :- !, form_to_pretty([forall|Rest], Pretty), pp:pr(Out, 72, Pretty),@@ -144,9 +153,6 @@ decl(Decl, Sort, SVars, End). quantifier_preds([], [], []).-quantifier_preds([(Var,mesg)|SVars], [Var|Vars], Preds) :-- !,- quantifier_preds(SVars, Vars, Preds). quantifier_preds([(Var,Sort)|SVars], [Var|Vars], [[Sort, Var]|Preds]) :- quantifier_preds(SVars, Vars, Preds).
+ src/scala/Main.scala view
@@ -0,0 +1,47 @@+package cpsaextras++import java.io._+import java.util.ResourceBundle;++object Main {++ /**+ * @param args the command line arguments+ */+ def main(args: Array[String]): Unit = {+ if (args.length != 1) {+ println("Usage: cpsaextras INPUT")+ println(getVersion())+ }+ else {+ val in = new BufferedReader(new FileReader(args(0)))+ val sr = new SExprReader(args(0), in)+ val out = new PrintWriter(System.out)+ while (true) {+ val x = sr.read()+ if (x == null) {+ out.close()+ return+ }+ Printer.pp(out, 80, 2, x)+ out.println()+ out.println()+ }+ }+ }++ private var resources: ResourceBundle = null++ private val VERSION_RESOURCES = "cpsaextras/version"++ /**+ * Get program name and a version number from a resource.+ */+ def getVersion() = {+ if (resources == null)+ resources = ResourceBundle.getBundle(VERSION_RESOURCES)+ val program = resources.getString("program")+ val version = resources.getString("version")+ program + " " + version+ }+}
+ src/scala/Pretty.scala view
@@ -0,0 +1,159 @@+/*+ * A simple pretty printer+ *+ * The alogithm is by Lawrence C. Paulson, who simplified an algorithm+ * by Derek C. Oppen.+ *+ * Derek C. Oppen, Prettyprinting, ACM Transactions on Programming+ * Languages and Systems, Vol 2, No. 4, October 1980, Pages 465-483.+ *+ * Copyright (c) 2010 The MITRE Corporation+ *+ * This program is free software: you can redistribute it and/or modify+ * it under the terms of the BSD License as published by the University+ * of California.+ */++/* A pretty printer based on ML programs with the following copyright++(**** ML Programs from Chapter 8 of++ ML for the Working Programmer, 2nd edition+ by Lawrence C. Paulson, Computer Laboratory, University of Cambridge.+ (Cambridge University Press, 1996)++Copyright (C) 1996 by Cambridge University Press.+Permission to copy without fee is granted provided that this copyright+notice and the DISCLAIMER OF WARRANTY are included in any copy.++DISCLAIMER OF WARRANTY. These programs are provided `as is' without+warranty of any kind. We make no warranties, express or implied, that the+programs are free of error, or are consistent with any particular standard+of merchantability, or that they will meet your requirements for any+particular application. They should not be relied upon for solving a+problem whose incorrect solution could result in injury to a person or loss+of property. If you do use the programs or functions in such a manner, it+is at your own risk. The author and publisher disclaim all liability for+direct, incidental or consequential damages resulting from your use of+these programs or functions.+****)++*/++package cpsaextras++import java.io.PrintWriter++/** Abstract data type for pretty printing. */+sealed abstract class Pretty+private case class Str(s: String) extends Pretty+private case class Brk(n: Int) extends Pretty+private case class Blo(l: List[Pretty], indent: Int, n: Int) extends Pretty+private case class Grp(l: List[Pretty], indent: Int, n: Int) extends Pretty++object Pretty {+ // Exported constructors++ /** Create a string.+ * @param s string to be printed+ */+ def str(s: String): Pretty = {+ Str(s)+ }++ /** Create a break point.+ * @param n number of spaces+ */+ def brk(n: Int): Pretty = {+ Brk(n)+ }++ /** Create an indentation block. When pretty printing, any of the+ * break points in the list can be used.+ * @param indent number of spaces to indent+ * @param es a list that includes break points+ */+ def blo(indent: Int, es: List[Pretty]): Pretty = {+ Blo(es, indent, len(es, 0))+ }++ /** Create an indentation group. When pretty printing,+ * either all or none of the break points are used.+ * @param indent number of spaces to indent+ * @param es a list that includes break points+ */+ def grp(indent: Int, es: List[Pretty]): Pretty = {+ Grp(es, indent, len(es, 0))+ }++ private def len(es: List[Pretty], n: Int): Int = {+ es match {+ case Nil => n+ case e :: es => len(es, size(e) + n)+ }+ }++ private def size(e: Pretty): Int = {+ e match {+ case Str(s) => s.length+ case Brk(n) => n+ case Blo(_, _, n) => n+ case Grp(_, _, n) => n+ }+ }++ /** Print an object of type Pretty. */+ def pr(w: PrintWriter, margin: Int, e: Pretty): Unit = {+ printing(w, margin, List(e), margin, 0, false, margin)+ }++ private def printing(w: PrintWriter, margin: Int, es: List[Pretty],+ blockspace:Int, after: Int, force: Boolean,+ space: Int): Int = {+ es match {+ case Nil => space+ case e :: es =>+ val space1 = e match {+ case Str(s) => // Place a string+ w.print(s)+ space - s.length+ case Brk(n) => // Place breakable space+ if (!force && n + breakdist(es, after) <= space)+ blanks(w, n, space) // Don't break+ else {+ w.println() // Break+ blanks(w, margin - blockspace, margin)+ }+ case Blo(bes, indent, _) => // Place a block+ printing(w, margin, bes, space - indent,+ breakdist(es, after), false, space)+ case Grp(bes, indent, n) => // Place a group+ val dist = breakdist(es, after)+ printing(w, margin, bes, space - indent,+ dist, n + dist > space, space)+ }+ printing(w, margin, es, blockspace, after, force, space1)+ }+ }++ // Find the distance to the nearest breakable space+ private def breakdist(es: List[Pretty], after: Int): Int = {+ es match {+ case Nil => after+ case Str(s) :: es => s.length + breakdist(es, after)+ case Brk(_) :: es => 0+ case Blo(_, _, n) :: es => n + breakdist(es, after)+ case Grp(_, _, n) :: es => n + breakdist(es, after)+ }+ }++ // Place spaces+ private def blanks(w: PrintWriter, n: Int, space: Int): Int = {+ if (n <= 0)+ space+ else {+ w.print(' ')+ blanks(w, n - 1, space - 1)+ }+ }+}
+ src/scala/Printer.scala view
@@ -0,0 +1,122 @@+/*+ * A CPSA specific pretty printer+ *+ * Copyright (c) 2009 The MITRE Corporation+ *+ * This program is free software: you can redistribute it and/or+ * modify it under the terms of the BSD License as published by the+ * University of California.+ */++package cpsaextras++import java.io.PrintWriter++object Printer {++ /** CPSA specific pretty printer.+ * The pretty printer that indents a constant amount for each list. The+ * top-level lists are laid out specially. Whenever some breaks+ * occur, all breaks are forced. Also, breaks are only placed before+ * strings and lists. CPSA protocols are handled specially. Each+ * defrole is handled as are top-level lists.+ *+ * @param w the output writer+ * @param margin the width to be filled+ * @param indent the number of spaces in an indent+ * @param x the S-expression to be pretty printed+ */+ def pp[A](w: PrintWriter, margin: Int, indent: Int, x: SExpr[A]): Unit = {+ Pretty.pr(w, margin, pretty(indent, x))+ }++ private def pretty[A](indent: Int, x: SExpr[A]): Pretty = {+ x match {+ case L(_, (x@S(_, "defprotocol")) :: xs) =>+ roles(indent, xs, List(block(indent, x), Pretty.str("(")))+ case x@L(_, S(_, "defmacro") :: _) =>+ block(indent, x)+ case x@L(_, S(_, "herald") :: _) =>+ block(indent, x)+ case _ =>+ group(indent, x)+ }+ }++ // Role specific pretty printer+ private def roles[A](indent: Int, xs: List[SExpr[A]],+ acc: List[Pretty]): Pretty = {+ xs match {+ case Nil =>+ Pretty.grp(indent, (Pretty.str(")") :: acc).reverse)+ case (x@S(_, _)) :: xs =>+ roles(indent, xs, block(indent, x) :: Pretty.str(" ") :: acc)+ case (x@Q(_, _)) :: xs =>+ roles(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)+ case (x@N(_, _)) :: xs =>+ roles(indent, xs, block(indent, x) :: Pretty.str(" ") :: acc)+ case (x@L(_, S(_, "defrole") :: _)) :: xs =>+ roles(indent, xs, group(indent, x) :: Pretty.brk(1) :: acc)+ case (x@L(_, _)) :: xs =>+ roles(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)+ }+ }++ // A pretty printer for top-level S-expressions+ private def group[A](indent: Int, x: SExpr[A]): Pretty = {+ x match {+ case L(a, l) => grouplist(indent, l)+ case _ => block(indent, x)+ }+ }++ private def grouplist[A](indent: Int, xs: List[SExpr[A]]): Pretty = {+ xs match {+ case Nil => Pretty.str("()")+ case x :: xs =>+ grouprest(indent, xs, List(block(indent, x), Pretty.str("(")))+ }+ }++ private def grouprest[A](indent: Int, xs: List[SExpr[A]],+ acc: List[Pretty]): Pretty = {+ xs match {+ case Nil =>+ Pretty.grp(indent, (Pretty.str(")") :: acc).reverse)+ case (x@S(_, _)) :: xs =>+ grouprest(indent, xs, block(indent, x) :: Pretty.str(" ") :: acc)+ case (x@Q(_, _)) :: xs =>+ grouprest(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)+ case (x@N(_, _)) :: xs =>+ grouprest(indent, xs, block(indent, x) :: Pretty.str(" ") :: acc)+ case (x@L(_, _)) :: xs =>+ grouprest(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)+ }+ }++ // A pretty printer for interior lists using block style breaking.+ private def block[A](indent: Int, x: SExpr[A]): Pretty = {+ x match {+ case L(a, l) => blocklist(indent, l)+ case _ => Pretty.str(x.toString())+ }+ }++ private def blocklist[A](indent: Int, xs: List[SExpr[A]]): Pretty = {+ xs match {+ case Nil => Pretty.str("()")+ case x :: xs =>+ blockrest(indent, xs, List(block(indent, x), Pretty.str("(")))+ }+ }++ private def blockrest[A](indent: Int, xs: List[SExpr[A]],+ acc: List[Pretty]): Pretty = {+ xs match {+ case Nil =>+ Pretty.blo(indent, (Pretty.str(")") :: acc).reverse)+ case x :: xs =>+ blockrest(indent, xs, block(indent, x) :: Pretty.brk(1) :: acc)+ }+ }+}
+ src/scala/SExpr.scala view
@@ -0,0 +1,282 @@+/*+ * S-expressions+ *+'* Copyright (c) 2010 The MITRE Corporation+ *+ * This program is free software: you can redistribute it and/or modify+ * it under the terms of the BSD License as published by the University+ * of California.+ */++package cpsaextras++import java.io._++/**+ * Annotated S-expressions. Each S-expression can be annotated with+ * something of type A.+ */+sealed abstract class SExpr[A] {+ /** The annotation. */+ val a: A+}+/** Case of a symbol. */+case class S[A](a: A, s: String) extends SExpr[A] {+ override def toString(): String = {+ s.toString()+ }+}+/** Case of a string. */+case class Q[A](a: A, q: String) extends SExpr[A] {+ override def toString(): String = {+ "\"" + q.toString() + "\""+ }+}+/** Case of a number. */+case class N[A](a: A, n: Int) extends SExpr[A] {+ override def toString(): String = {+ n.toString()+ }+}+/** Case of a list of S-expressions. */+case class L[A](a: A, l: List[SExpr[A]]) extends SExpr[A] {+ override def toString(): String = {+ l.toString()+ }+}++/** The file position annotation. */+final case class Pos(file: String, line: Int, column: Int) {+ override def toString (): String = {+ file + ":" + line + ":" + column + ": "+ }+}++/** An S-expression reader.+ *+ * @param file name of the input file+ * @param in stream associated with the input file+ */+class SExprReader(file: String, in: Reader) {+ private var line = 1 // Stream line number+ private var column = 1 // Stream column++ // A scanner token+ private sealed abstract class Token+ // A token for a non-list S-expression+ private case class Atom(a: SExpr[Pos]) extends Token+ // A token for the left parenthesis+ private case class LParen(p: Pos) extends Token+ // A token for the right parenthesis+ private case class RParen(p: Pos) extends Token+ // A token for end-of-file+ private case object Eof extends Token++ /**+ * Reads an S-expression annotated with file positions.+ * @return an S-expression or null on end-of-file+ */+ def read(): SExpr[Pos] = {+ scan() match {+ case Atom(a) => a+ case LParen(p) => list(p, Nil)+ case RParen(p) =>+ in.close()+ throw new IOException(p + "Close of unopened list")+ case Eof =>+ in.close()+ null+ }+ }++ // Parse a non top-level list+ private def list(pos: Pos, acc: List[SExpr[Pos]]): SExpr[Pos] = {+ scan() match {+ case Atom(a) => list(pos, a :: acc)+ case LParen(p) => list(pos, list(p, Nil) :: acc)+ case RParen(_) => L(pos, acc.reverse)+ case Eof =>+ in.close()+ throw new IOException(pos + "Unexpected end of input in list")+ }+ }++ // Scanner++ // Consume white space and then dispatch on the first character+ private def scan(): Token = {+ val ch = get()+ if (Character.isWhitespace(ch))+ scan()+ else ch match {+ case -1 => Eof+ case '(' => LParen(Pos(file, line, column))+ case ')' => RParen(Pos(file, line, column))+ case ';' => comment()+ case _ => atom(ch)+ }+ }++ // Consume a comment and then resume scanning+ private def comment(): Token = {+ get() match {+ case -1 => Eof+ case '\n' => scan()+ case _ => comment()+ }+ }++ // Scan an atom+ private def atom(ch: Int): Token = {+ val p = Pos(file, line, column) // Position of atom+ ch match {+ case '"' => string(p, new StringBuilder())+ case '+' => numOrSym(p, singleton(ch))+ case '-' => numOrSym(p, singleton(ch))+ case _ =>+ if (Character.isDigit(ch))+ number(p, singleton(ch))+ else if (isSym(ch))+ symbol(p, singleton(ch))+ else {+ in.close()+ throw new IOException(p + "Bad char in atom")+ }+ }+ }++ // Create a string buffer with one character+ private def singleton(ch: Int): StringBuilder = {+ val sb = new StringBuilder()+ sb.append(ch.toChar)+ sb+ }++ // Scan a string atom+ private def string(p: Pos, sb: StringBuilder): Token = {+ val ch = get()+ if (ch == -1) {+ in.close()+ throw new IOException(p + "End of input in string")+ }+ else if (ch == '"')+ Atom(Q(p, sb.toString().intern()))+ else if (isStr(ch)) {+ sb.append(ch.toChar)+ string(p, sb)+ }+ else {+ in.close()+ throw new IOException(p + "Bad char for string")+ }+ }++ // Scan a number atom+ private def number(p: Pos, sb: StringBuilder): Token = {+ val ch = peek()+ if (ch == -1)+ Atom(N(p, Integer.parseInt(sb.toString())))+ else if (Character.isDigit(ch)) {+ get()+ sb.append(ch.toChar)+ number(p, sb)+ }+ else if (isSym(ch)) {+ in.close()+ throw new IOException(p + "Bad char after number")+ }+ else+ Atom(N(p, Integer.parseInt(sb.toString())))+ }++ // See if an atom is an number or a symbol+ private def numOrSym(p: Pos, sb: StringBuilder): Token = {+ val ch = peek()+ if (ch == -1)+ symbol(p, sb)+ else if (Character.isDigit(ch))+ number(p, sb)+ else+ symbol(p, sb)+ }++ // Scan a symbol+ private def symbol(p: Pos, sb: StringBuilder): Token = {+ val ch = peek()+ if (ch == -1)+ Atom(S(p, sb.toString().intern()))+ else if (isSym(ch)) {+ get()+ sb.append(ch.toChar)+ symbol(p, sb)+ }+ else+ Atom(S(p, sb.toString().intern()))+ }++ // Is character a constituent of a symbol?+ private def isSym(ch: Int) = {+ ch match {+ case '+' => true+ case '-' => true+ case '*' => true+ case '/' => true+ case '<' => true+ case '=' => true+ case '>' => true+ case '!' => true+ case '?' => true+ case ':' => true+ case '$' => true+ case '%' => true+ case '_' => true+ case '&' => true+ case '~' => true+ case '^' => true+ case _ => Character.isLetterOrDigit(ch)+ }+ }++ // Is character a constituent of a string?+ private def isStr(ch: Int) = {+ ch match {+ case '"' => false+ case '\\' => false+ case _ => !Character.isISOControl(ch)+ }+ }++ // Character reader with look ahead++ private var peeked = false // Is look ahead active?+ private var seen = 0 // peeked character++ // Get next character and set the current file position.+ private def get(): Int = {+ val next =+ if (peeked) {+ peeked = false+ seen+ }+ else+ in.read()+ if (next == '\n') {+ line += 1+ column = 1+ }+ else+ column += 1+ next+ }++ // Read ahead if need be+ private def peek(): Int = {+ if (peeked)+ seen+ else {+ peeked = true+ seen = in.read()+ seen+ }+ }+}
tst/DH_hack.tst view
@@ -1,6 +1,6 @@ (herald "DH Hack" (bound 15)) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from DH_hack.scm") (comment "Strand count bounded at 15")
tst/blanchet.tst view
@@ -1,7 +1,7 @@ (herald "Blanchet's Simple Example Protocol" (comment "There is a flaw in this protocol by design")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from blanchet.scm") (defprotocol blanchet basic
tst/completeness-test.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from completeness-test.scm") (defprotocol completeness-test basic
tst/crushing.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from crushing.scm") (defprotocol crushing basic
tst/dass_simple.tst view
@@ -1,6 +1,6 @@ (herald "Distributed Authentication Security Service Protocol Variants") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from dass_simple.scm") (defprotocol dass-simple basic
tst/denning-sacco.tst view
@@ -1,6 +1,6 @@ (herald "Denning-Sacco Protocol") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from denning-sacco.scm") (defprotocol denning-sacco basic
tst/deorig_contract.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from deorig_contract.scm") (defprotocol deorig-contract basic
tst/deorig_mesg.tst view
@@ -1,6 +1,6 @@ (herald deorig-mesg) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from deorig_mesg.scm") (defprotocol deorig-mesg basic
tst/deorig_simple.tst view
@@ -1,6 +1,6 @@ (herald deorig-simple) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from deorig_simple.scm") (defprotocol deorig-simple basic
tst/dy.tst view
@@ -1,6 +1,6 @@ (herald "Example 1.3 from 1983 Dolev-Yao Paper") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from dy.lsp") (defprotocol dy basic
tst/encsig.tst view
@@ -1,7 +1,7 @@ (herald "Encrypted Signed Message Example" (comment "Shows examples of key usage of asymmetric keys")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from encsig.scm") (defprotocol mult-keys-enc-sig basic
tst/epmo-hash.tst view
@@ -1,7 +1,7 @@ (herald "Electronic Purchase with Money Order Protocol with Key Hashing" (comment "Annotated with trust management formulas")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from epmo-hash.scm") (defprotocol epmo basic
tst/epmo-key-hash.tst view
@@ -1,7 +1,7 @@ (herald "Electronic Purchase with Money Order Protocol with Key Hashing" (comment "Annotated with trust management formulas")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from epmo-key-hash.scm") (defprotocol epmo basic
tst/epmo.tst view
@@ -1,7 +1,7 @@ (herald "Electronic Purchase with Money Order Protocol" (comment "Annotated with trust management formulas")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from epmo.scm") (defprotocol epmo basic
tst/epmo_acctnum-key-hash.tst view
@@ -2,7 +2,7 @@ "Electronic Purchase with Money Order Protocol Variant with Key Hashing" (comment "This version includes account numbers in exchanges")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from epmo_acctnum-key-hash.scm") (defprotocol epmo_acctnum basic
tst/ffgg.tst view
@@ -1,7 +1,7 @@ (herald "The ffgg Protocol" (comment "From A Necessarily Parallel Attack by Jon K. Millen")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from ffgg.scm") (defprotocol ffgg basic
tst/fragile_pruning.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from fragile_pruning.scm") (defprotocol fragile_pruning basic
+ tst/goals.scm view
@@ -0,0 +1,355 @@+(herald goals)++;;; Some authentication goals++;;; Unilateral authentication++(defprotocol unilateral basic+ (defrole init+ (vars (a name) (n text))+ (trace+ (send (enc n (pubk a)))+ (recv n)))+ (defrole resp+ (vars (a name) (n text))+ (trace+ (recv (enc n (pubk a)))+ (send n))))++(defgoal unilateral+ (forall ((a name) (n text) (z0 node))+ (implies+ (and + (p "init" 1 z0)+ (p "init" "n" z0 n)+ (p "init" "a" z0 a)+ (non (privk a))+ (uniq n))+ (exists ((z1 node))+ (and+ (p "resp" 1 z1)+ (p "resp" "a" z1 a)))))+ (comment "Authentication goal"))++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace+ (send (enc n1 a (pubk b)))+ (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace+ (recv (enc n1 a (pubk b)))+ (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++;;; Does initiator satisfy the unilateral authentication goal?++;;; Note that the goal requires translation of some of the role+;;; specific predicates.+(defgoal ns+ (forall ((a name) (n text) (z0 node))+ (implies+ (and + (p "init" 1 z0)+ (p "init" "n1" z0 n)+ (p "init" "b" z0 a)+ (non (privk a))+ (uniq n))+ (exists ((z1 node))+ (and+ (p "resp" 1 z1)+ (p "resp" "b" z1 a)))))+ (comment "Initiator authentication goal")+ (comment "Same as unilateral goal under the predicate mapping:")+ (comment (p "init" "n") "->" (p "init" "n1") "and")+ (comment (p "init" "a") "->" (p "init" "b") "and")+ (comment (p "resp" "a") "->" (p "resp" "b")))+ +;;; Does responder satisfy the unilateral authentication goal?++(defgoal ns+ (forall ((a name) (n text) (z0 node))+ (implies+ (and + (p "resp" 2 z0)+ (p "resp" "n2" z0 n)+ (p "resp" "a" z0 a)+ (non (privk a))+ (uniq n))+ (exists ((z1 node))+ (and+ (p "init" 2 z1)+ (p "init" "a" z1 a)))))+ (comment "Responder authentication goal")+ (comment "Same as unilateral goal under the predicate mapping:")+ (comment (p "init" 1) "->" (p "resp" 2) "and")+ (comment (p "init" "n") "->" (p "resp" "n2") "and")+ (comment (p "init" "a") "->" (p "resp" "a") "and")+ (comment (p "resp" 1) "->" (p "init" 2) "and")+ (comment (p "resp" "a") "->" (p "init" "a")))++(defgoal ns+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and + (p "init" 1 z0)+ (p "init" "n1" z0 n)+ (p "init" "a" z0 a)+ (p "init" "b" z0 b)+ (non (privk a))+ (non (privk b))+ (uniq n))+ (exists ((z1 node))+ (and+ (p "resp" 1 z1)+ (p "resp" "b" z1 b)))))+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and + (p "init" 1 z0)+ (p "init" "n1" z0 n)+ (p "init" "a" z0 a)+ (p "init" "b" z0 b)+ (non (privk a))+ (non (privk b))+ (uniq n))+ (exists ((z1 node))+ (and+ (p "resp" 1 z1)+ (p "resp" "a" z1 a)))))+ (comment "Double initiator authentication goal"))+ +(defgoal ns+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and + (p "resp" 2 z0)+ (p "resp" "n2" z0 n)+ (p "resp" "a" z0 a)+ (p "resp" "b" z0 b)+ (non (privk a))+ (non (privk b))+ (uniq n))+ (exists ((z1 node))+ (and+ (p "init" 2 z1)+ (p "init" "a" z1 a)))))+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and + (p "resp" 2 z0)+ (p "resp" "n2" z0 n)+ (p "resp" "a" z0 a)+ (p "resp" "b" z0 b)+ (non (privk a))+ (non (privk b))+ (uniq n))+ (exists ((z1 node))+ (and+ (p "init" 2 z1)+ (p "init" "b" z1 b)))))+ (comment "Double responder authentication goal"))++;;; Old stuff++;;; The initiator point-of-view+(defskeleton ns+ (vars (a b name) (n1 text))+ (defstrand init 3 (a a) (b b) (n1 n1))+ (non-orig (privk b) (privk a))+ (uniq-orig n1)+ (goals+ (forall ((a b name) (n1 text) (no nu node))+ (implies+ (and (p "init" 2 no)+ (p "init" "a" no a)+ (p "init" "b" no b)+ (p "init" "n1" no n1)+ (p "init" 0 nu)+ (str-prec nu no)+ (non (privk a))+ (non (privk b))+ (uniq-at n1 nu))+ (exists ((na nb node))+ (and (p "init" 2 na)+ (p "resp" 1 nb)+ (p "init" "b" na b)+ (p "resp" "b" nb b))))))+ (comment "Initiator point-of-view"))++(defgoal ns+ (forall ((a b name) (n1 text) (no nu node))+ (implies+ (and (p "init" 2 no)+ (p "init" "a" no a)+ (p "init" "b" no b)+ (p "init" "n1" no n1)+ (p "init" 0 nu)+ (str-prec nu no)+ (non (privk a))+ (non (privk b))+ (uniq-at n1 nu))+ (exists ((na nb node))+ (and (p "init" 2 na)+ (p "resp" 1 nb)+ (p "init" "b" na b)+ (p "resp" "b" nb b)))))+ (comment "Initiator point-of-view"))++;;; The responder point-of-view+(defskeleton ns+ (vars (a name) (n2 text))+ (defstrand resp 3 (a a) (n2 n2))+ (non-orig (privk a))+ (uniq-orig n2)+ (goals+ (forall ((n2 n1 text) (a b name) (z z-0 node))+ (implies+ (and (p "resp" 1 z) (p "resp" 2 z-0) (p "resp" "n2" z-0 n2)+ (p "resp" "n1" z-0 n1) (p "resp" "b" z-0 b) (p "resp" "a" z-0 a)+ (str-prec z z-0) (non (privk a)) (uniq-at n2 z))+ (exists ((b-0 name) (z-1 z-2 node))+ (and (p "init" 1 z-1) (p "init" 2 z-2) (p "init" "n1" z-2 n1)+ (p "init" "n2" z-2 n2) (p "init" "a" z-2 a)+ (p "init" "b" z-2 b-0) (prec z z-1) (prec z-2 z-0)+ (str-prec z-1 z-2))))))+ (comment "Responder point-of-view"))++;;; The responder point-of-view+(defskeleton ns+ (vars (a name) (n2 text))+ (defstrand resp 3 (a a) (n2 n2))+ (non-orig (privk a))+ (uniq-orig n2)+ (goals+ (forall ((n2 n1 text) (a b name) (z z-0 node))+ (implies+ (and (p "resp" 1 z) (p "resp" 2 z-0) (p "resp" "n2" z-0 n2)+ (p "resp" "n1" z-0 n1) (p "resp" "b" z-0 b) (p "resp" "a" z-0 a)+ (str-prec z z-0) (non (privk a)) (uniq-at n2 z))+ (exists ((b-0 name) (z-1 z-2 node))+ (and (p "init" 1 z-1) (p "init" 2 z-2) (p "init" "n1" z-2 n1)+ (p "init" "n2" z-2 n2) (p "init" "a" z-2 a)+ (p "init" "b" z-2 b-0) (prec z z-1) (prec z-2 z-0)+ (str-prec z-1 z-2))))))+ (comment "Responder point-of-view"))++;;; Double initiator point-of-view+(defskeleton ns+ (vars (a b name) (n1 n1-0 text))+ (defstrand init 3 (a a) (b b) (n1 n1))+ (defstrand init 3 (a a) (b b) (n1 n1-0))+ (non-orig (privk b) (privk a))+ (uniq-orig n1 n1-0)+ (goals+ (forall ((n1 n1-0 n2 n2-0 text) (a b name) (z z-0 z-1 z-2 node))+ (implies+ (and (p "init" 0 z) (p "init" 2 z-0) (p "init" 0 z-1)+ (p "init" 2 z-2) (p "init" "n1" z-0 n1) (p "init" "n2" z-0 n2)+ (p "init" "a" z-0 a) (p "init" "b" z-0 b)+ (p "init" "n1" z-2 n1-0) (p "init" "n2" z-2 n2-0)+ (p "init" "a" z-2 a) (p "init" "b" z-2 b) (str-prec z z-0)+ (str-prec z-1 z-2) (non (privk a)) (non (privk b))+ (uniq-at n1 z) (uniq-at n1-0 z-1))+ (= z-1 z))))+ (comment "Double initiator point-of-view"))++;;; Needham-Schroeder Protocol with origination assumptions on roles+;;; This++(defprotocol ns-role-origs basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace+ (send (enc n1 a (pubk b)))+ (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ (non-orig (privk b))+ (uniq-orig n1))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace+ (recv (enc n1 a (pubk b)))+ (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ (non-orig (privk a))+ (uniq-orig n2))+ (comment "Needham-Schroeder with role assumptions that are too strong"))++;;; The initiator point-of-view+(defskeleton ns-role-origs+ (vars)+ (defstrand init 3))++;;; The responder point-of-view+(defskeleton ns-role-origs+ (vars)+ (defstrand resp 3))++;;; Needham-Schroeder Protocol with a doubled nonce. Look at the+;;; first message in each role.++(defprotocol ns2 basic+ (defrole init+ (vars (a b name) (n1 n2 n3 text))+ (trace+ (send (enc n1 n3 a (pubk b)))+ (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace+ (recv (enc n1 n1 a (pubk b)))+ (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ (note doubled nonce in the first message))+ (note that this protocol is derived from Needham-Schroeder))++(defskeleton ns2+ (vars (a b name) (n1 text))+ (defstrand init 3 (a a) (b b) (n1 n1))+ (non-orig (privk b) (privk a))+ (uniq-orig n1)+ (note the disappearance of this note))++;;; Note that the association list style key-value pairs that follow+;;; the list of strands can be supplied in any order, and values with+;;; the same key are appended together. Check the output to see how+;;; CPSA interprets this input.+(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n2 n2) (n1 n1) (b b) (a a))+ (non-orig (privk b))+ (precedes ((0 0) (1 0)))+ (non-orig (privk a))+ (uniq-orig n1)+ (precedes ((1 1) (0 1))))++(defprotocol nsl-typeless basic+ (defrole init+ (vars (a b name) (n1 text) (n2 mesg))+ (trace+ (send (enc a n1 (pubk b)))+ (recv (enc n1 n2 b (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 text) (n1 mesg))+ (trace+ (recv (enc a n1 (pubk b)))+ (send (enc n1 n2 b (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder-Lowe with untyped nonces"))++;;; The responder point-of-view+(defskeleton nsl-typeless+ (vars (a b name) (n2 text))+ (defstrand resp 2 (a a) (n2 n2) (b b))+ (deflistener n2)+ (non-orig (privk a) (privk b))+ (uniq-orig n2)+ (comment "Shows typeflaw in typeless NSL"))
+ tst/goals.tst view
@@ -0,0 +1,1117 @@+(herald goals)++(comment "CPSA 2.5.0")+(comment "All input read from goals.scm")++(defprotocol unilateral basic+ (defrole init+ (vars (a name) (n text))+ (trace (send (enc n (pubk a))) (recv n)))+ (defrole resp+ (vars (a name) (n text))+ (trace (recv (enc n (pubk a))) (send n))))++(defskeleton unilateral+ (vars (n text) (a name))+ (defstrand init 2 (n n) (a a))+ (non-orig (privk a))+ (uniq-orig n)+ (goals+ (forall ((a name) (n text) (z0 node))+ (implies+ (and (p "init" 1 z0) (p "init" "n" z0 n) (p "init" "a" z0 a)+ (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "a" z1 a))))))+ (comment "Authentication goal")+ (traces ((send (enc n (pubk a))) (recv n)))+ (label 0)+ (unrealized (0 1))+ (origs (n (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton unilateral+ (vars (n text) (a name))+ (defstrand init 2 (n n) (a a))+ (defstrand resp 2 (n n) (a a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a))+ (uniq-orig n)+ (operation nonce-test (added-strand resp 2) n (0 1) (enc n (pubk a)))+ (traces ((send (enc n (pubk a))) (recv n))+ ((recv (enc n (pubk a))) (send n)))+ (label 1)+ (parent 0)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((a a) (n n))))+ (origs (n (0 0))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n n2 text) (a a-0 name))+ (defstrand init 2 (n1 n) (n2 n2) (a a-0) (b a))+ (non-orig (privk a))+ (uniq-orig n)+ (goals+ (forall ((a name) (n text) (z0 node))+ (implies+ (and (p "init" 1 z0) (p "init" "n1" z0 n) (p "init" "b" z0 a)+ (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "b" z1 a))))))+ (comment "Initiator authentication goal"+ "Same as unilateral goal under the predicate mapping:"+ (p "init" "n") "->" (p "init" "n1") "and" (p "init" "a") "->"+ (p "init" "b") "and" (p "resp" "a") "->" (p "resp" "b"))+ (traces ((send (enc n a-0 (pubk a))) (recv (enc n n2 (pubk a-0)))))+ (label 2)+ (unrealized (0 1))+ (origs (n (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n n2 n2-0 text) (a a-0 name))+ (defstrand init 2 (n1 n) (n2 n2) (a a-0) (b a))+ (defstrand resp 2 (n1 n) (n2 n2-0) (a a-0) (b a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a))+ (uniq-orig n)+ (operation nonce-test (added-strand resp 2) n (0 1)+ (enc n a-0 (pubk a)))+ (traces ((send (enc n a-0 (pubk a))) (recv (enc n n2 (pubk a-0))))+ ((recv (enc n a-0 (pubk a))) (send (enc n n2-0 (pubk a-0)))))+ (label 3)+ (parent 2)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((a a) (n n) (a-0 a-0) (n2 n2))))+ (origs (n (0 0))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n n1 text) (a b name))+ (defstrand resp 3 (n1 n1) (n2 n) (a a) (b b))+ (non-orig (privk a))+ (uniq-orig n)+ (goals+ (forall ((a name) (n text) (z0 node))+ (implies+ (and (p "resp" 2 z0) (p "resp" "n2" z0 n) (p "resp" "a" z0 a)+ (non (privk a)) (uniq n))+ (exists ((z1 node))+ (and (p "init" 2 z1) (p "init" "a" z1 a))))))+ (comment "Responder authentication goal"+ "Same as unilateral goal under the predicate mapping:" (p "init" 1)+ "->" (p "resp" 2) "and" (p "init" "n") "->" (p "resp" "n2") "and"+ (p "init" "a") "->" (p "resp" "a") "and" (p "resp" 1) "->"+ (p "init" 2) "and" (p "resp" "a") "->" (p "init" "a"))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n (pubk a)))+ (recv (enc n (pubk b)))))+ (label 4)+ (unrealized (0 2))+ (origs (n (0 1)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n n1 text) (a b b-0 name))+ (defstrand resp 3 (n1 n1) (n2 n) (a a) (b b))+ (defstrand init 3 (n1 n1) (n2 n) (a a) (b b-0))+ (precedes ((0 1) (1 1)) ((1 2) (0 2)))+ (non-orig (privk a))+ (uniq-orig n)+ (operation nonce-test (added-strand init 3) n (0 2)+ (enc n1 n (pubk a)))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n (pubk a)))+ (recv (enc n (pubk b))))+ ((send (enc n1 a (pubk b-0))) (recv (enc n1 n (pubk a)))+ (send (enc n (pubk b-0)))))+ (label 5)+ (parent 4)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((a a) (n n) (b b) (n1 n1))))+ (origs (n (0 1))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n n2 text) (a b name))+ (defstrand init 2 (n1 n) (n2 n2) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n)+ (goals+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and (p "init" 1 z0) (p "init" "n1" z0 n) (p "init" "a" z0 a)+ (p "init" "b" z0 b) (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node)) (and (p "resp" 1 z1) (p "resp" "b" z1 b)))))+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and (p "init" 1 z0) (p "init" "n1" z0 n) (p "init" "a" z0 a)+ (p "init" "b" z0 b) (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node))+ (and (p "resp" 1 z1) (p "resp" "a" z1 a))))))+ (comment "Double initiator authentication goal")+ (traces ((send (enc n a (pubk b))) (recv (enc n n2 (pubk a)))))+ (label 6)+ (unrealized (0 1))+ (origs (n (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n n2 n2-0 text) (a b name))+ (defstrand init 2 (n1 n) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n) (n2 n2-0) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n)+ (operation nonce-test (added-strand resp 2) n (0 1)+ (enc n a (pubk b)))+ (traces ((send (enc n a (pubk b))) (recv (enc n n2 (pubk a))))+ ((recv (enc n a (pubk b))) (send (enc n n2-0 (pubk a)))))+ (label 7)+ (parent 6)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n n2 text) (a b name))+ (defstrand init 2 (n1 n) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n) (n2 n2) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n)+ (operation nonce-test (contracted (n2-0 n2)) n (0 1)+ (enc n n2 (pubk a)) (enc n a (pubk b)))+ (traces ((send (enc n a (pubk b))) (recv (enc n n2 (pubk a))))+ ((recv (enc n a (pubk b))) (send (enc n n2 (pubk a)))))+ (label 8)+ (parent 7)+ (unrealized)+ (shape)+ (satisfies yes yes)+ (maps ((0) ((a a) (b b) (n n) (n2 n2))))+ (origs (n (0 0))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n n1 text) (a b name))+ (defstrand resp 3 (n1 n1) (n2 n) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n)+ (goals+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and (p "resp" 2 z0) (p "resp" "n2" z0 n) (p "resp" "a" z0 a)+ (p "resp" "b" z0 b) (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node)) (and (p "init" 2 z1) (p "init" "a" z1 a)))))+ (forall ((a b name) (n text) (z0 node))+ (implies+ (and (p "resp" 2 z0) (p "resp" "n2" z0 n) (p "resp" "a" z0 a)+ (p "resp" "b" z0 b) (non (privk a)) (non (privk b)) (uniq n))+ (exists ((z1 node))+ (and (p "init" 2 z1) (p "init" "b" z1 b))))))+ (comment "Double responder authentication goal")+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n (pubk a)))+ (recv (enc n (pubk b)))))+ (label 9)+ (unrealized (0 2))+ (origs (n (0 1)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n n1 text) (a b b-0 name))+ (defstrand resp 3 (n1 n1) (n2 n) (a a) (b b))+ (defstrand init 3 (n1 n1) (n2 n) (a a) (b b-0))+ (precedes ((0 1) (1 1)) ((1 2) (0 2)))+ (non-orig (privk a) (privk b))+ (uniq-orig n)+ (operation nonce-test (added-strand init 3) n (0 2)+ (enc n1 n (pubk a)))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n (pubk a)))+ (recv (enc n (pubk b))))+ ((send (enc n1 a (pubk b-0))) (recv (enc n1 n (pubk a)))+ (send (enc n (pubk b-0)))))+ (label 10)+ (parent 9)+ (unrealized)+ (shape)+ (satisfies yes (no (a a) (b b) (n n) (z0 (0 2))))+ (maps ((0) ((a a) (b b) (n n) (n1 n1))))+ (origs (n (0 1))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (goals+ (forall ((a b name) (n1 text) (no nu node))+ (implies+ (and (p "init" 2 no) (p "init" "a" no a) (p "init" "b" no b)+ (p "init" "n1" no n1) (p "init" 0 nu) (str-prec nu no)+ (non (privk a)) (non (privk b)) (uniq-at n1 nu))+ (exists ((na nb node))+ (and (p "init" 2 na) (p "resp" 1 nb) (p "init" "b" na b)+ (p "resp" "b" nb b))))))+ (comment "Initiator point-of-view")+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (label 11)+ (unrealized (0 1))+ (origs (n1 (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2-0) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation nonce-test (added-strand resp 2) n1 (0 1)+ (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))+ (label 12)+ (parent 11)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation nonce-test (contracted (n2-0 n2)) n1 (0 1)+ (enc n1 n2 (pubk a)) (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))))+ (label 13)+ (parent 12)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((a a) (b b) (n1 n1) (n2 n2))))+ (origs (n1 (0 0))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (goals+ (forall ((a b name) (n1 text) (no nu node))+ (implies+ (and (p "init" 2 no) (p "init" "a" no a) (p "init" "b" no b)+ (p "init" "n1" no n1) (p "init" 0 nu) (str-prec nu no)+ (non (privk a)) (non (privk b)) (uniq-at n1 nu))+ (exists ((na nb node))+ (and (p "init" 2 na) (p "resp" 1 nb) (p "init" "b" na b)+ (p "resp" "b" nb b))))))+ (comment "Initiator point-of-view")+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (label 14)+ (unrealized (0 1))+ (origs (n1 (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2-0) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation nonce-test (added-strand resp 2) n1 (0 1)+ (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))+ (label 15)+ (parent 14)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation nonce-test (contracted (n2-0 n2)) n1 (0 1)+ (enc n1 n2 (pubk a)) (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))))+ (label 16)+ (parent 15)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((a a) (b b) (n1 n1) (n2 n2))))+ (origs (n1 (0 0))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n2 n1 text) (a b name))+ (defstrand resp 3 (n1 n1) (n2 n2) (a a) (b b))+ (non-orig (privk a))+ (uniq-orig n2)+ (goals+ (forall ((n2 n1 text) (a b name) (z z-0 node))+ (implies+ (and (p "resp" 1 z) (p "resp" 2 z-0) (p "resp" "n2" z-0 n2)+ (p "resp" "n1" z-0 n1) (p "resp" "b" z-0 b)+ (p "resp" "a" z-0 a) (str-prec z z-0) (non (privk a))+ (uniq-at n2 z))+ (exists ((b-0 name) (z-1 z-2 node))+ (and (p "init" 1 z-1) (p "init" 2 z-2) (p "init" "n1" z-2 n1)+ (p "init" "n2" z-2 n2) (p "init" "a" z-2 a)+ (p "init" "b" z-2 b-0) (prec z z-1) (prec z-2 z-0)+ (str-prec z-1 z-2))))))+ (comment "Responder point-of-view")+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (label 17)+ (unrealized (0 2))+ (origs (n2 (0 1)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n2 n1 text) (a b b-0 name))+ (defstrand resp 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b-0))+ (precedes ((0 1) (1 1)) ((1 2) (0 2)))+ (non-orig (privk a))+ (uniq-orig n2)+ (operation nonce-test (added-strand init 3) n2 (0 2)+ (enc n1 n2 (pubk a)))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ ((send (enc n1 a (pubk b-0))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b-0)))))+ (label 18)+ (parent 17)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((a a) (n2 n2) (b b) (n1 n1))))+ (origs (n2 (0 1))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n2 n1 text) (a b name))+ (defstrand resp 3 (n1 n1) (n2 n2) (a a) (b b))+ (non-orig (privk a))+ (uniq-orig n2)+ (goals+ (forall ((n2 n1 text) (a b name) (z z-0 node))+ (implies+ (and (p "resp" 1 z) (p "resp" 2 z-0) (p "resp" "n2" z-0 n2)+ (p "resp" "n1" z-0 n1) (p "resp" "b" z-0 b)+ (p "resp" "a" z-0 a) (str-prec z z-0) (non (privk a))+ (uniq-at n2 z))+ (exists ((b-0 name) (z-1 z-2 node))+ (and (p "init" 1 z-1) (p "init" 2 z-2) (p "init" "n1" z-2 n1)+ (p "init" "n2" z-2 n2) (p "init" "a" z-2 a)+ (p "init" "b" z-2 b-0) (prec z z-1) (prec z-2 z-0)+ (str-prec z-1 z-2))))))+ (comment "Responder point-of-view")+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (label 19)+ (unrealized (0 2))+ (origs (n2 (0 1)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n2 n1 text) (a b b-0 name))+ (defstrand resp 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b-0))+ (precedes ((0 1) (1 1)) ((1 2) (0 2)))+ (non-orig (privk a))+ (uniq-orig n2)+ (operation nonce-test (added-strand init 3) n2 (0 2)+ (enc n1 n2 (pubk a)))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ ((send (enc n1 a (pubk b-0))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b-0)))))+ (label 20)+ (parent 19)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((a a) (n2 n2) (b b) (n1 n1))))+ (origs (n2 (0 1))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n1 n1-0 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand init 3 (n1 n1-0) (n2 n2-0) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n1 n1-0)+ (goals+ (forall ((n1 n1-0 n2 n2-0 text) (a b name) (z z-0 z-1 z-2 node))+ (implies+ (and (p "init" 0 z) (p "init" 2 z-0) (p "init" 0 z-1)+ (p "init" 2 z-2) (p "init" "n1" z-0 n1) (p "init" "n2" z-0 n2)+ (p "init" "a" z-0 a) (p "init" "b" z-0 b)+ (p "init" "n1" z-2 n1-0) (p "init" "n2" z-2 n2-0)+ (p "init" "a" z-2 a) (p "init" "b" z-2 b) (str-prec z z-0)+ (str-prec z-1 z-2) (non (privk a)) (non (privk b))+ (uniq-at n1 z) (uniq-at n1-0 z-1)) (= z-1 z))))+ (comment "Double initiator point-of-view")+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((send (enc n1-0 a (pubk b))) (recv (enc n1-0 n2-0 (pubk a)))+ (send (enc n2-0 (pubk b)))))+ (label 21)+ (unrealized (0 1) (1 1))+ (origs (n1 (0 0)) (n1-0 (1 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation collapsed 1 0)+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (label 22)+ (parent 21)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n1-0 n2 n2-0 n2-1 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand init 3 (n1 n1-0) (n2 n2-0) (a a) (b b))+ (defstrand resp 2 (n1 n1-0) (n2 n2-1) (a a) (b b))+ (precedes ((1 0) (2 0)) ((2 1) (1 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1 n1-0)+ (operation nonce-test (added-strand resp 2) n1-0 (1 1)+ (enc n1-0 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((send (enc n1-0 a (pubk b))) (recv (enc n1-0 n2-0 (pubk a)))+ (send (enc n2-0 (pubk b))))+ ((recv (enc n1-0 a (pubk b))) (send (enc n1-0 n2-1 (pubk a)))))+ (label 23)+ (parent 21)+ (unrealized (0 1) (1 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2-0) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation nonce-test (added-strand resp 2) n1 (0 1)+ (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))+ (label 24)+ (parent 22)+ (unrealized (0 1))+ (origs (n1 (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n1-0 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand init 3 (n1 n1-0) (n2 n2-0) (a a) (b b))+ (defstrand resp 2 (n1 n1-0) (n2 n2-0) (a a) (b b))+ (precedes ((1 0) (2 0)) ((2 1) (1 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1 n1-0)+ (operation nonce-test (contracted (n2-1 n2-0)) n1-0 (1 1)+ (enc n1-0 n2-0 (pubk a)) (enc n1-0 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((send (enc n1-0 a (pubk b))) (recv (enc n1-0 n2-0 (pubk a)))+ (send (enc n2-0 (pubk b))))+ ((recv (enc n1-0 a (pubk b))) (send (enc n1-0 n2-0 (pubk a)))))+ (label 25)+ (parent 23)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation nonce-test (contracted (n2-0 n2)) n1 (0 1)+ (enc n1 n2 (pubk a)) (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))))+ (label 26)+ (parent 24)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0 0) ((a a) (b b) (n1 n1) (n1-0 n1) (n2 n2) (n2-0 n2))))+ (origs (n1 (0 0))))++(defskeleton ns+ (vars (n1 n1-0 n2 n2-0 n2-1 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand init 3 (n1 n1-0) (n2 n2-0) (a a) (b b))+ (defstrand resp 2 (n1 n1-0) (n2 n2-0) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2-1) (a a) (b b))+ (precedes ((0 0) (3 0)) ((1 0) (2 0)) ((2 1) (1 1)) ((3 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1 n1-0)+ (operation nonce-test (added-strand resp 2) n1 (0 1)+ (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((send (enc n1-0 a (pubk b))) (recv (enc n1-0 n2-0 (pubk a)))+ (send (enc n2-0 (pubk b))))+ ((recv (enc n1-0 a (pubk b))) (send (enc n1-0 n2-0 (pubk a))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2-1 (pubk a)))))+ (label 27)+ (parent 25)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n1-0 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2-0) (a a) (b b))+ (defstrand init 3 (n1 n1-0) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1-0) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2-0) (a a) (b b))+ (precedes ((0 0) (3 0)) ((1 0) (2 0)) ((2 1) (1 1)) ((3 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1 n1-0)+ (operation nonce-test (contracted (n2-1 n2-0)) n1 (0 1)+ (enc n1 n2-0 (pubk a)) (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2-0 (pubk a)))+ (send (enc n2-0 (pubk b))))+ ((send (enc n1-0 a (pubk b))) (recv (enc n1-0 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1-0 a (pubk b))) (send (enc n1-0 n2 (pubk a))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))+ (label 28)+ (parent 27)+ (unrealized)+ (shape)+ (satisfies+ (no (n1-0 n1) (n1 n1-0) (n2-0 n2-0) (n2 n2) (a a) (b b) (z-2 (0 0))+ (z-1 (0 2)) (z-0 (1 0)) (z (1 2))))+ (maps ((0 1) ((a a) (b b) (n1 n1) (n1-0 n1-0) (n2 n2-0) (n2-0 n2))))+ (origs (n1 (0 0)) (n1-0 (1 0))))++(comment "Nothing left to do")++(defprotocol ns-role-origs basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ (non-orig (privk b))+ (uniq-orig n1))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ (non-orig (privk a))+ (uniq-orig n2))+ (comment+ "Needham-Schroeder with role assumptions that are too strong"))++(defskeleton ns-role-origs+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (non-orig (privk b))+ (uniq-orig n1)+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (label 29)+ (unrealized (0 1))+ (origs (n1 (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns-role-origs+ (vars (n1 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n2 n2-0) (n1 n1) (b b) (a a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1 n2-0)+ (operation nonce-test (added-strand resp 2) n1 (0 1)+ (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))+ (label 30)+ (parent 29)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns-role-origs+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n2 n2) (n1 n1) (b b) (a a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1 n2)+ (operation nonce-test (contracted (n2-0 n2)) n1 (0 1)+ (enc n1 n2 (pubk a)) (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))))+ (label 31)+ (parent 30)+ (unrealized)+ (shape)+ (maps ((0) ((a a) (b b) (n1 n1) (n2 n2))))+ (origs (n2 (1 1)) (n1 (0 0))))++(comment "Nothing left to do")++(defprotocol ns-role-origs basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ (non-orig (privk b))+ (uniq-orig n1))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ (non-orig (privk a))+ (uniq-orig n2))+ (comment+ "Needham-Schroeder with role assumptions that are too strong"))++(defskeleton ns-role-origs+ (vars (n2 n1 text) (b a name))+ (defstrand resp 3 (n2 n2) (n1 n1) (b b) (a a))+ (non-orig (privk a))+ (uniq-orig n2)+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (label 32)+ (unrealized (0 2))+ (origs (n2 (0 1)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns-role-origs+ (vars (n2 n1 text) (b a b-0 name))+ (defstrand resp 3 (n2 n2) (n1 n1) (b b) (a a))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b-0))+ (precedes ((0 1) (1 1)) ((1 0) (0 0)) ((1 2) (0 2)))+ (non-orig (privk a) (privk b-0))+ (uniq-orig n2 n1)+ (operation nonce-test (added-strand init 3) n2 (0 2)+ (enc n1 n2 (pubk a)))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ ((send (enc n1 a (pubk b-0))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b-0)))))+ (label 33)+ (parent 32)+ (unrealized (0 0) (0 2))+ (comment "2 in cohort - 2 not yet seen"))++(defskeleton ns-role-origs+ (vars (n2 n1 text) (a b name))+ (defstrand resp 3 (n2 n2) (n1 n1) (b b) (a a))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (precedes ((0 1) (1 1)) ((1 0) (0 0)) ((1 2) (0 2)))+ (non-orig (privk a) (privk b))+ (uniq-orig n2 n1)+ (operation nonce-test (contracted (b-0 b)) n1 (0 0)+ (enc n1 a (pubk b)))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (label 34)+ (parent 33)+ (unrealized)+ (shape)+ (maps ((0) ((b b) (a a) (n2 n2) (n1 n1))))+ (origs (n1 (1 0)) (n2 (0 1))))++(defskeleton ns-role-origs+ (vars (n2 n1 n2-0 text) (b a b-0 name))+ (defstrand resp 3 (n2 n2) (n1 n1) (b b) (a a))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b-0))+ (defstrand resp 2 (n2 n2-0) (n1 n1) (b b-0) (a a))+ (precedes ((0 1) (1 1)) ((1 0) (2 0)) ((1 2) (0 2)) ((2 1) (0 0)))+ (non-orig (privk a) (privk b-0))+ (uniq-orig n2 n1 n2-0)+ (operation nonce-test (added-strand resp 2) n1 (0 0)+ (enc n1 a (pubk b-0)))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ ((send (enc n1 a (pubk b-0))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b-0))))+ ((recv (enc n1 a (pubk b-0))) (send (enc n1 n2-0 (pubk a)))))+ (label 35)+ (parent 33)+ (unrealized (0 0) (0 2))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns-role-origs+ (vars (n2 n1 n2-0 text) (a b name))+ (defstrand resp 3 (n2 n2) (n1 n1) (b b) (a a))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n2 n2-0) (n1 n1) (b b) (a a))+ (precedes ((0 1) (1 1)) ((1 0) (2 0)) ((1 2) (0 2)) ((2 1) (0 0)))+ (non-orig (privk a) (privk b))+ (uniq-orig n2 n1 n2-0)+ (operation nonce-test (contracted (b-0 b)) n1 (0 0)+ (enc n1 n2-0 (pubk a)) (enc n1 a (pubk b)))+ (traces+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))+ (label 36)+ (parent 35)+ (seen 34)+ (unrealized)+ (comment "1 in cohort - 0 not yet seen"))++(comment "Nothing left to do")++(defprotocol ns2 basic+ (defrole init+ (vars (a b name) (n1 n2 n3 text))+ (trace (send (enc n1 n3 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace (recv (enc n1 n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b))))+ (note doubled nonce in the first message))+ (note that this protocol is derived from Needham-Schroeder))++(defskeleton ns2+ (vars (n1 n2 n3 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (n3 n3) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (traces+ ((send (enc n1 n3 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (label 37)+ (unrealized (0 1))+ (origs (n1 (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns2+ (vars (n2 n3 n2-0 text) (a b name))+ (defstrand init 3 (n1 n3) (n2 n2) (n3 n3) (a a) (b b))+ (defstrand resp 2 (n2 n2-0) (n1 n3) (b b) (a a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n3)+ (operation nonce-test (added-strand resp 2) n3 (0 1)+ (enc n3 n3 a (pubk b)))+ (traces+ ((send (enc n3 n3 a (pubk b))) (recv (enc n3 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n3 n3 a (pubk b))) (send (enc n3 n2-0 (pubk a)))))+ (label 38)+ (parent 37)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns2+ (vars (n3 n2 text) (a b name))+ (defstrand init 3 (n1 n3) (n2 n2) (n3 n3) (a a) (b b))+ (defstrand resp 2 (n2 n2) (n1 n3) (b b) (a a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n3)+ (operation nonce-test (contracted (n2-0 n2)) n3 (0 1)+ (enc n3 n2 (pubk a)) (enc n3 n3 a (pubk b)))+ (traces+ ((send (enc n3 n3 a (pubk b))) (recv (enc n3 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n3 n3 a (pubk b))) (send (enc n3 n2 (pubk a)))))+ (label 39)+ (parent 38)+ (unrealized)+ (shape)+ (maps ((0) ((a a) (b b) (n1 n3) (n2 n2) (n3 n3))))+ (origs (n3 (0 0))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (a b name) (n1 n2 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n1 n1) (n2 n2) (a a) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))))+ (label 40)+ (unrealized)+ (shape)+ (maps ((0 1) ((n1 n1) (n2 n2) (a a) (b b))))+ (origs (n1 (0 0))))++(comment "Nothing left to do")++(defprotocol nsl-typeless basic+ (defrole init+ (vars (a b name) (n1 text) (n2 mesg))+ (trace (send (enc a n1 (pubk b))) (recv (enc n1 n2 b (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 text) (n1 mesg))+ (trace (recv (enc a n1 (pubk b))) (send (enc n1 n2 b (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder-Lowe with untyped nonces"))++(defskeleton nsl-typeless+ (vars (n1 mesg) (n2 text) (a b name))+ (defstrand resp 2 (n1 n1) (n2 n2) (b b) (a a))+ (deflistener n2)+ (non-orig (privk a) (privk b))+ (uniq-orig n2)+ (comment "Shows typeflaw in typeless NSL")+ (traces ((recv (enc a n1 (pubk b))) (send (enc n1 n2 b (pubk a))))+ ((recv n2) (send n2)))+ (label 41)+ (unrealized (1 0))+ (preskeleton)+ (comment "Not a skeleton"))++(defskeleton nsl-typeless+ (vars (n1 mesg) (n2 text) (a b name))+ (defstrand resp 2 (n1 n1) (n2 n2) (b b) (a a))+ (deflistener n2)+ (precedes ((0 1) (1 0)))+ (non-orig (privk a) (privk b))+ (uniq-orig n2)+ (traces ((recv (enc a n1 (pubk b))) (send (enc n1 n2 b (pubk a))))+ ((recv n2) (send n2)))+ (label 42)+ (parent 41)+ (unrealized (1 0))+ (origs (n2 (0 1)))+ (comment "2 in cohort - 2 not yet seen"))++(defskeleton nsl-typeless+ (vars (n2 n1 text) (a b name))+ (defstrand resp 2 (n1 n1) (n2 n2) (b b) (a a))+ (deflistener n2)+ (defstrand init 3 (n2 n2) (n1 n1) (a a) (b b))+ (precedes ((0 1) (2 1)) ((2 2) (1 0)))+ (non-orig (privk a) (privk b))+ (uniq-orig n2)+ (operation nonce-test (added-strand init 3) n2 (1 0)+ (enc n1 n2 b (pubk a)))+ (traces ((recv (enc a n1 (pubk b))) (send (enc n1 n2 b (pubk a))))+ ((recv n2) (send n2))+ ((send (enc a n1 (pubk b))) (recv (enc n1 n2 b (pubk a)))+ (send (enc n2 (pubk b)))))+ (label 43)+ (parent 42)+ (unrealized (1 0))+ (comment "empty cohort"))++(defskeleton nsl-typeless+ (vars (n2 n2-0 text) (a b a-0 name))+ (defstrand resp 2 (n1 a-0) (n2 n2) (b b) (a a))+ (deflistener n2)+ (defstrand resp 2 (n1 (cat n2 b)) (n2 n2-0) (b a) (a a-0))+ (precedes ((0 1) (2 0)) ((2 1) (1 0)))+ (non-orig (privk a) (privk b))+ (uniq-orig n2)+ (operation nonce-test (added-strand resp 2) n2 (1 0)+ (enc a-0 n2 b (pubk a)))+ (traces ((recv (enc a a-0 (pubk b))) (send (enc a-0 n2 b (pubk a))))+ ((recv n2) (send n2))+ ((recv (enc a-0 n2 b (pubk a)))+ (send (enc (cat n2 b) n2-0 a (pubk a-0)))))+ (label 44)+ (parent 42)+ (unrealized)+ (shape)+ (maps ((0 1) ((a a) (b b) (n2 n2) (n1 a-0))))+ (origs (n2 (0 1))))++(comment "Nothing left to do")
tst/hashtest-key-hash.tst view
@@ -1,6 +1,6 @@ (herald "Hashtest") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from hashtest-key-hash.scm") (defprotocol hashtest basic
tst/hashtest.tst view
@@ -1,6 +1,6 @@ (herald "Hashtest") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from hashtest.scm") (defprotocol hashtest basic
tst/incompleteness_example.tst view
@@ -1,7 +1,7 @@ (herald incompleteness-example (comment "Shows a shape not found by CPSA")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from incompleteness_example.scm") (defprotocol incompleteness-example basic
tst/isoreject.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from isoreject.scm") (defprotocol isoreject basic
tst/kelly1.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from kelly1.scm") (defprotocol kelly1 basic
tst/kerberos.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from kerberos.scm") (defprotocol kerberos basic
tst/mass.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from mass.lsp") (defprotocol mass basic
tst/mass2.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from mass2.lsp") (defprotocol mass2 basic
tst/missing_contraction.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from missing_contraction.scm") (defprotocol missing-contraction basic
tst/neuman-stubblebine-reauth.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from neuman-stubblebine-reauth.lsp") (defprotocol neuman-stubblebine-reauth basic
tst/neuman-stubblebine.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from neuman-stubblebine.scm") (defprotocol neuman-stubblebine basic
tst/no_contraction.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from no_contraction.scm") (defprotocol no-contraction basic
tst/non_transforming.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from non_transforming.scm") (defprotocol non_transforming basic
tst/nonaug-prune.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from nonaug-prune.scm") (defprotocol nonaug-prune basic
tst/ns-l.tst view
@@ -1,7 +1,7 @@ (herald "Needham-Schroeder-Low Public-Key Protocol" (comment "With deflistener's")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from ns-l.scm") (defprotocol ns basic
tst/ns.scm view
@@ -32,6 +32,15 @@ (uniq-orig n1 n1-0) (comment "Double initiator point-of-view")) +;;; Double initiator point-of-view, same nonce+(defskeleton ns+ (vars (a b name) (n1 text))+ (defstrand init 3 (a a) (b b) (n1 n1))+ (defstrand init 3 (a a) (b b) (n1 n1))+ (non-orig (privk b) (privk a))+ (uniq-orig n1)+ (comment "Double initiator point-of-view, same nonce"))+ ;;; The responder point-of-view (defskeleton ns (vars (a name) (n2 text))
tst/ns.tst view
@@ -1,6 +1,6 @@ (herald "Needham-Schroeder Public-Key Protocol Variants") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from ns.scm") (defprotocol ns basic@@ -253,6 +253,88 @@ (comment "Needham-Schroeder with no role origination assumptions")) (defskeleton ns+ (vars (n1 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand init 3 (n1 n1) (n2 n2-0) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (comment "Double initiator point-of-view, same nonce")+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2-0 (pubk a)))+ (send (enc n2-0 (pubk b)))))+ (label 11)+ (unrealized)+ (preskeleton)+ (comment "Not a skeleton"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (label 12)+ (parent 11)+ (unrealized (0 1))+ (origs (n1 (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 n2-0 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n2 n2-0) (n1 n1) (b b) (a a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation nonce-test (added-strand resp 2) n1 (0 1)+ (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))+ (label 13)+ (parent 12)+ (unrealized (0 1))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton ns+ (vars (n1 n2 text) (a b name))+ (defstrand init 3 (n1 n1) (n2 n2) (a a) (b b))+ (defstrand resp 2 (n2 n2) (n1 n1) (b b) (a a))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk a) (privk b))+ (uniq-orig n1)+ (operation nonce-test (contracted (n2-0 n2)) n1 (0 1)+ (enc n1 n2 (pubk a)) (enc n1 a (pubk b)))+ (traces+ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b))))+ ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))))+ (label 14)+ (parent 13)+ (unrealized)+ (shape)+ (maps ((0) ((a a) (b b) (n1 n1) (n2 n2))))+ (origs (n1 (0 0))))++(comment "Nothing left to do")++(defprotocol ns basic+ (defrole init+ (vars (a b name) (n1 n2 text))+ (trace (send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a)))+ (send (enc n2 (pubk b)))))+ (defrole resp+ (vars (b a name) (n2 n1 text))+ (trace (recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))+ (recv (enc n2 (pubk b)))))+ (comment "Needham-Schroeder with no role origination assumptions"))++(defskeleton ns (vars (n2 n1 text) (a b name)) (defstrand resp 3 (n2 n2) (n1 n1) (b b) (a a)) (non-orig (privk a))@@ -261,7 +343,7 @@ (traces ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a))) (recv (enc n2 (pubk b)))))- (label 11)+ (label 15) (unrealized (0 2)) (origs (n2 (0 1))) (comment "1 in cohort - 1 not yet seen"))@@ -280,8 +362,8 @@ (recv (enc n2 (pubk b)))) ((send (enc n1 a (pubk b-0))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b-0)))))- (label 12)- (parent 11)+ (label 16)+ (parent 15) (unrealized) (shape) (maps ((0) ((a a) (n2 n2) (b b) (n1 n1))))@@ -313,7 +395,7 @@ (traces ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b)))))- (label 13)+ (label 17) (unrealized (0 1)) (origs (n1 (0 0))) (comment "1 in cohort - 1 not yet seen"))@@ -331,8 +413,8 @@ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b)))) ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))- (label 14)- (parent 13)+ (label 18)+ (parent 17) (unrealized (0 1)) (comment "1 in cohort - 1 not yet seen")) @@ -349,8 +431,8 @@ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b)))) ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))))- (label 15)- (parent 14)+ (label 19)+ (parent 18) (unrealized) (shape) (maps ((0) ((a a) (b b) (n1 n1) (n2 n2))))@@ -382,7 +464,7 @@ (traces ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a))) (recv (enc n2 (pubk b)))))- (label 16)+ (label 20) (unrealized (0 2)) (origs (n2 (0 1))) (comment "1 in cohort - 1 not yet seen"))@@ -401,8 +483,8 @@ (recv (enc n2 (pubk b)))) ((send (enc n1 a (pubk b-0))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b-0)))))- (label 17)- (parent 16)+ (label 21)+ (parent 20) (unrealized (0 0) (0 2)) (comment "2 in cohort - 2 not yet seen")) @@ -420,8 +502,8 @@ (recv (enc n2 (pubk b)))) ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b)))))- (label 18)- (parent 17)+ (label 22)+ (parent 21) (unrealized) (shape) (maps ((0) ((b b) (a a) (n2 n2) (n1 n1))))@@ -443,8 +525,8 @@ ((send (enc n1 a (pubk b-0))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b-0)))) ((recv (enc n1 a (pubk b-0))) (send (enc n1 n2-0 (pubk a)))))- (label 19)- (parent 17)+ (label 23)+ (parent 21) (unrealized (0 0) (0 2)) (comment "1 in cohort - 1 not yet seen")) @@ -464,9 +546,9 @@ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b)))) ((recv (enc n1 a (pubk b))) (send (enc n1 n2-0 (pubk a)))))- (label 20)- (parent 19)- (seen 18)+ (label 24)+ (parent 23)+ (seen 22) (unrealized) (comment "1 in cohort - 0 not yet seen")) @@ -492,7 +574,7 @@ (traces ((send (enc n1 n3 a (pubk b))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b)))))- (label 21)+ (label 25) (unrealized (0 1)) (origs (n1 (0 0))) (comment "1 in cohort - 1 not yet seen"))@@ -510,8 +592,8 @@ ((send (enc n3 n3 a (pubk b))) (recv (enc n3 n2 (pubk a))) (send (enc n2 (pubk b)))) ((recv (enc n3 n3 a (pubk b))) (send (enc n3 n2-0 (pubk a)))))- (label 22)- (parent 21)+ (label 26)+ (parent 25) (unrealized (0 1)) (comment "1 in cohort - 1 not yet seen")) @@ -528,8 +610,8 @@ ((send (enc n3 n3 a (pubk b))) (recv (enc n3 n2 (pubk a))) (send (enc n2 (pubk b)))) ((recv (enc n3 n3 a (pubk b))) (send (enc n3 n2 (pubk a)))))- (label 23)- (parent 22)+ (label 27)+ (parent 26) (unrealized) (shape) (maps ((0) ((a a) (b b) (n1 n3) (n2 n2) (n3 n3))))@@ -559,7 +641,7 @@ ((send (enc n1 a (pubk b))) (recv (enc n1 n2 (pubk a))) (send (enc n2 (pubk b)))) ((recv (enc n1 a (pubk b))) (send (enc n1 n2 (pubk a)))))- (label 24)+ (label 28) (unrealized) (shape) (maps ((0 1) ((n1 n1) (n2 n2) (a a) (b b))))@@ -587,7 +669,7 @@ (comment "Shows typeflaw in typeless NSL") (traces ((recv (enc a n1 (pubk b))) (send (enc n1 n2 b (pubk a)))) ((recv n2) (send n2)))- (label 25)+ (label 29) (unrealized (1 0)) (preskeleton) (comment "Not a skeleton"))@@ -601,8 +683,8 @@ (uniq-orig n2) (traces ((recv (enc a n1 (pubk b))) (send (enc n1 n2 b (pubk a)))) ((recv n2) (send n2)))- (label 26)- (parent 25)+ (label 30)+ (parent 29) (unrealized (1 0)) (origs (n2 (0 1))) (comment "2 in cohort - 2 not yet seen"))@@ -621,8 +703,8 @@ ((recv n2) (send n2)) ((send (enc a n1 (pubk b))) (recv (enc n1 n2 b (pubk a))) (send (enc n2 (pubk b)))))- (label 27)- (parent 26)+ (label 31)+ (parent 30) (unrealized (1 0)) (comment "empty cohort")) @@ -640,8 +722,8 @@ ((recv n2) (send n2)) ((recv (enc a-0 n2 b (pubk a))) (send (enc (cat n2 b) n2-0 a (pubk a-0)))))- (label 28)- (parent 26)+ (label 32)+ (parent 30) (unrealized) (shape) (maps ((0 1) ((a a) (b b) (n2 n2) (n1 a-0))))
tst/nsl3.tst view
@@ -1,6 +1,6 @@ (herald "Three Party Needham-Schroeder-Lowe Protocol") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from nsl3.scm") (defprotocol nsl3 basic
tst/nsl4cm1.tst view
file too large to diff
tst/nslsk.tst view
@@ -1,6 +1,6 @@ (herald "Needham-Schroeder-Lowe Protocol with symmetric encryption") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from nslsk.scm") (defprotocol nslsk basic
tst/or.tst view
@@ -1,7 +1,7 @@ (herald "Otway-Rees Protocol" (comment "Standard version using variables of sort mesg")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from or.scm") (defprotocol or basic
tst/pca.tst view
@@ -1,7 +1,7 @@ (herald "Privacy Certificate Authority" (bound 15) (comment "Generation of an Attestation Identity Certificate")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from pca.scm") (comment "Strand count bounded at 15")
tst/pen-non-orig-test.tst view
@@ -1,6 +1,6 @@ (herald "pen-non-orig test") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from pen-non-orig-test.scm") (defprotocol pennonorigtest basic
tst/pkinit.tst view
@@ -1,6 +1,6 @@ (herald "Kerberos PK init") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from pkinit.scm") (defprotocol pkinit basic
tst/preprocess.tst view
@@ -1,6 +1,6 @@ (herald "Pre-processing test example: modified NS with two responders") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from preprocess.scm") (defprotocol ns basic
tst/print.tst view
@@ -1,7 +1,7 @@ (herald "Print Test" (comment "See if read forms look like printed ones")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from print.scm") (defprotocol print-test basic
tst/pruning1.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from pruning1.scm") (defprotocol prune basic
tst/sigenc.tst view
@@ -1,7 +1,7 @@ (herald "Signed Encrypted Message Example" (comment "Shows examples of key usage of asymmetric keys")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from sigenc.scm") (defprotocol mult-keys-sig-enc basic
tst/sorted_epmo_acctnum.tst view
@@ -4,7 +4,7 @@ "This version uses sorts to avoid confusion" "between a nonce and other data")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from sorted_epmo_acctnum.scm") (comment "Strand count bounded at 12")
tst/targetterms2.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from targetterms2.scm") (defprotocol targetterms2 basic
tst/targetterms6.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from targetterms6.scm") (defprotocol targetterms6 basic
tst/targetterms8.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from targetterms8.scm") (defprotocol targetterms8 basic
tst/timestamping.tst view
@@ -1,6 +1,6 @@ (herald timestamping-service) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from timestamping.scm") (defprotocol timestamping-service basic
tst/uncarried_keys.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from uncarried_keys.scm") (defprotocol uncarried-keys basic
+ tst/unilateral.scm view
@@ -0,0 +1,92 @@+(herald unilateral)++(defprotocol unilateral basic+ (defrole init+ (vars (n text) (k akey))+ (trace+ (send (enc n k))+ (recv n))+ (uniq-orig n))+ (defrole resp+ (vars (n text) (k akey))+ (trace+ (recv (enc n k))+ (send n))))++(defskeleton unilateral+ (vars (k akey))+ (defstrand init 2 (k k))+ (non-orig (invk k)))++(defskeleton unilateral+ (vars (n text) (k akey))+ (defstrand resp 2 (n n) (k k))+ (pen-non-orig n)+ (non-orig (invk k)))++;;; The same two problems posed using security goals. The goals were+;;; taken from the output of cpsasas.++(defgoal unilateral+ (forall ((n text) (k akey) (z z-0 node))+ (implies+ (and (p "init" 0 z) (p "init" 1 z-0) (p "init" "n" z-0 n)+ (p "init" "k" z-0 k) (str-prec z z-0) (non (invk k))+ (uniq-at n z))+ (exists ((z-1 z-2 node))+ (and (p "resp" 0 z-1) (p "resp" 1 z-2) (p "resp" "n" z-2 n)+ (p "resp" "k" z-2 k) (prec z z-1) (prec z-2 z-0)+ (str-prec z-1 z-2))))))++(defgoal unilateral+ (forall ((n text) (k akey) (z node))+ (implies+ (and (p "resp" 1 z) (p "resp" "n" z n) (p "resp" "k" z k)+ (non (invk k)) (pnon n))+ (exists ((k-0 akey) (z-0 z-1 node))+ (and (p "resp" 0 z-0) (p "init" 0 z-1) (p "init" "n" z-1 n)+ (p "init" "k" z-1 k-0) (prec z-1 z-0) (str-prec z-0 z)+ (uniq-at n z-1))))))++;;; Unilateral authentication from ISO/IEC JTC 1/SC 27/WG 2 N1050++(defprotocol iso-unilateral basic+ (defrole resp+ (vars (na nb t1 t2 t3 text) (b name))+ (trace+ (recv (cat nb t1))+ (send (cat na nb b t3 (enc na nb b t2 (privk b)))))+ (uniq-orig na))+ (defrole init+ (vars (na nb t1 t2 t3 text) (b name))+ (trace+ (send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b)))))+ (uniq-orig nb))+ (comment "Two pass authentication"))++(defskeleton iso-unilateral+ (vars (b name))+ (defstrand init 2 (b b))+ (non-orig (privk b)))++;;; Same as above, but also checking to see if there was agreement.+(defgoal iso-unilateral+ (forall ((b name) (z node))+ (implies+ (and (p "init" 1 z)+ (p "init" "b" z b)+ (non (privk b)))+ (exists ((y node))+ (and (p "resp" 1 y)+ (p "resp" "b" y b))))))++;;; Silly example. Of course the shape produced does not satisfy this+;;; goal!+(defgoal iso-unilateral+ (forall ((b name) (z node))+ (implies+ (and (p "init" 1 z)+ (p "init" "b" z b)+ (non (privk b)))+ (false))))
+ tst/unilateral.tst view
@@ -0,0 +1,336 @@+(herald unilateral)++(comment "CPSA 2.5.0")+(comment "All input read from unilateral.scm")++(defprotocol unilateral basic+ (defrole init+ (vars (n text) (k akey))+ (trace (send (enc n k)) (recv n))+ (uniq-orig n))+ (defrole resp+ (vars (n text) (k akey))+ (trace (recv (enc n k)) (send n))))++(defskeleton unilateral+ (vars (n text) (k akey))+ (defstrand init 2 (n n) (k k))+ (non-orig (invk k))+ (uniq-orig n)+ (traces ((send (enc n k)) (recv n)))+ (label 0)+ (unrealized (0 1))+ (origs (n (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton unilateral+ (vars (n text) (k akey))+ (defstrand init 2 (n n) (k k))+ (defstrand resp 2 (n n) (k k))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (invk k))+ (uniq-orig n)+ (operation nonce-test (added-strand resp 2) n (0 1) (enc n k))+ (traces ((send (enc n k)) (recv n)) ((recv (enc n k)) (send n)))+ (label 1)+ (parent 0)+ (unrealized)+ (shape)+ (maps ((0) ((k k) (n n))))+ (origs (n (0 0))))++(comment "Nothing left to do")++(defprotocol unilateral basic+ (defrole init+ (vars (n text) (k akey))+ (trace (send (enc n k)) (recv n))+ (uniq-orig n))+ (defrole resp+ (vars (n text) (k akey))+ (trace (recv (enc n k)) (send n))))++(defskeleton unilateral+ (vars (n text) (k akey))+ (defstrand resp 2 (n n) (k k))+ (non-orig (invk k))+ (pen-non-orig n)+ (traces ((recv (enc n k)) (send n)))+ (label 2)+ (unrealized (0 0))+ (origs)+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton unilateral+ (vars (n text) (k k-0 akey))+ (defstrand resp 2 (n n) (k k))+ (defstrand init 1 (n n) (k k-0))+ (precedes ((1 0) (0 0)))+ (non-orig (invk k))+ (pen-non-orig n)+ (uniq-orig n)+ (operation nonce-test (added-strand init 1) n (0 0))+ (traces ((recv (enc n k)) (send n)) ((send (enc n k-0))))+ (label 3)+ (parent 2)+ (unrealized)+ (shape)+ (maps ((0) ((n n) (k k))))+ (origs (n (1 0))))++(comment "Nothing left to do")++(defprotocol unilateral basic+ (defrole init+ (vars (n text) (k akey))+ (trace (send (enc n k)) (recv n))+ (uniq-orig n))+ (defrole resp+ (vars (n text) (k akey))+ (trace (recv (enc n k)) (send n))))++(defskeleton unilateral+ (vars (n text) (k akey))+ (defstrand init 2 (n n) (k k))+ (non-orig (invk k))+ (uniq-orig n)+ (goals+ (forall ((n text) (k akey) (z z-0 node))+ (implies+ (and (p "init" 0 z) (p "init" 1 z-0) (p "init" "n" z-0 n)+ (p "init" "k" z-0 k) (str-prec z z-0) (non (invk k))+ (uniq-at n z))+ (exists ((z-1 z-2 node))+ (and (p "resp" 0 z-1) (p "resp" 1 z-2) (p "resp" "n" z-2 n)+ (p "resp" "k" z-2 k) (prec z z-1) (prec z-2 z-0)+ (str-prec z-1 z-2))))))+ (traces ((send (enc n k)) (recv n)))+ (label 4)+ (unrealized (0 1))+ (origs (n (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton unilateral+ (vars (n text) (k akey))+ (defstrand init 2 (n n) (k k))+ (defstrand resp 2 (n n) (k k))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (invk k))+ (uniq-orig n)+ (operation nonce-test (added-strand resp 2) n (0 1) (enc n k))+ (traces ((send (enc n k)) (recv n)) ((recv (enc n k)) (send n)))+ (label 5)+ (parent 4)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((n n) (k k))))+ (origs (n (0 0))))++(comment "Nothing left to do")++(defprotocol unilateral basic+ (defrole init+ (vars (n text) (k akey))+ (trace (send (enc n k)) (recv n))+ (uniq-orig n))+ (defrole resp+ (vars (n text) (k akey))+ (trace (recv (enc n k)) (send n))))++(defskeleton unilateral+ (vars (n text) (k akey))+ (defstrand resp 2 (n n) (k k))+ (non-orig (invk k))+ (pen-non-orig n)+ (goals+ (forall ((n text) (k akey) (z node))+ (implies+ (and (p "resp" 1 z) (p "resp" "n" z n) (p "resp" "k" z k)+ (non (invk k)) (pnon n))+ (exists ((k-0 akey) (z-0 z-1 node))+ (and (p "resp" 0 z-0) (p "init" 0 z-1) (p "init" "n" z-1 n)+ (p "init" "k" z-1 k-0) (prec z-1 z-0) (str-prec z-0 z)+ (uniq-at n z-1))))))+ (traces ((recv (enc n k)) (send n)))+ (label 6)+ (unrealized (0 0))+ (origs)+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton unilateral+ (vars (n text) (k k-0 akey))+ (defstrand resp 2 (n n) (k k))+ (defstrand init 1 (n n) (k k-0))+ (precedes ((1 0) (0 0)))+ (non-orig (invk k))+ (pen-non-orig n)+ (uniq-orig n)+ (operation nonce-test (added-strand init 1) n (0 0))+ (traces ((recv (enc n k)) (send n)) ((send (enc n k-0))))+ (label 7)+ (parent 6)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((n n) (k k))))+ (origs (n (1 0))))++(comment "Nothing left to do")++(defprotocol iso-unilateral basic+ (defrole resp+ (vars (na nb t1 t2 t3 text) (b name))+ (trace (recv (cat nb t1))+ (send (cat na nb b t3 (enc na nb b t2 (privk b)))))+ (uniq-orig na))+ (defrole init+ (vars (na nb t1 t2 t3 text) (b name))+ (trace (send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b)))))+ (uniq-orig nb))+ (comment "Two pass authentication"))++(defskeleton iso-unilateral+ (vars (na nb t1 t2 t3 text) (b name))+ (defstrand init 2 (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3) (b b))+ (non-orig (privk b))+ (uniq-orig nb)+ (traces+ ((send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b))))))+ (label 8)+ (unrealized (0 1))+ (origs (nb (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton iso-unilateral+ (vars (na nb t1 t2 t3 t1-0 t3-0 text) (b name))+ (defstrand init 2 (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3) (b b))+ (defstrand resp 2 (na na) (nb nb) (t1 t1-0) (t2 t2) (t3 t3-0) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk b))+ (uniq-orig na nb)+ (operation encryption-test (added-strand resp 2)+ (enc na nb b t2 (privk b)) (0 1))+ (traces+ ((send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b)))))+ ((recv (cat nb t1-0))+ (send (cat na nb b t3-0 (enc na nb b t2 (privk b))))))+ (label 9)+ (parent 8)+ (unrealized)+ (shape)+ (maps ((0) ((b b) (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3))))+ (origs (na (1 1)) (nb (0 0))))++(comment "Nothing left to do")++(defprotocol iso-unilateral basic+ (defrole resp+ (vars (na nb t1 t2 t3 text) (b name))+ (trace (recv (cat nb t1))+ (send (cat na nb b t3 (enc na nb b t2 (privk b)))))+ (uniq-orig na))+ (defrole init+ (vars (na nb t1 t2 t3 text) (b name))+ (trace (send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b)))))+ (uniq-orig nb))+ (comment "Two pass authentication"))++(defskeleton iso-unilateral+ (vars (na nb t1 t2 t3 text) (b name))+ (defstrand init 2 (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3) (b b))+ (non-orig (privk b))+ (uniq-orig nb)+ (goals+ (forall ((b name) (z node))+ (implies (and (p "init" 1 z) (p "init" "b" z b) (non (privk b)))+ (exists ((y node)) (and (p "resp" 1 y) (p "resp" "b" y b))))))+ (traces+ ((send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b))))))+ (label 10)+ (unrealized (0 1))+ (origs (nb (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton iso-unilateral+ (vars (na nb t1 t2 t3 t1-0 t3-0 text) (b name))+ (defstrand init 2 (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3) (b b))+ (defstrand resp 2 (na na) (nb nb) (t1 t1-0) (t2 t2) (t3 t3-0) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk b))+ (uniq-orig na nb)+ (operation encryption-test (added-strand resp 2)+ (enc na nb b t2 (privk b)) (0 1))+ (traces+ ((send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b)))))+ ((recv (cat nb t1-0))+ (send (cat na nb b t3-0 (enc na nb b t2 (privk b))))))+ (label 11)+ (parent 10)+ (unrealized)+ (shape)+ (satisfies yes)+ (maps ((0) ((b b) (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3))))+ (origs (na (1 1)) (nb (0 0))))++(comment "Nothing left to do")++(defprotocol iso-unilateral basic+ (defrole resp+ (vars (na nb t1 t2 t3 text) (b name))+ (trace (recv (cat nb t1))+ (send (cat na nb b t3 (enc na nb b t2 (privk b)))))+ (uniq-orig na))+ (defrole init+ (vars (na nb t1 t2 t3 text) (b name))+ (trace (send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b)))))+ (uniq-orig nb))+ (comment "Two pass authentication"))++(defskeleton iso-unilateral+ (vars (na nb t1 t2 t3 text) (b name))+ (defstrand init 2 (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3) (b b))+ (non-orig (privk b))+ (uniq-orig nb)+ (goals+ (forall ((b name) (z node))+ (implies (and (p "init" 1 z) (p "init" "b" z b) (non (privk b)))+ (false))))+ (traces+ ((send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b))))))+ (label 12)+ (unrealized (0 1))+ (origs (nb (0 0)))+ (comment "1 in cohort - 1 not yet seen"))++(defskeleton iso-unilateral+ (vars (na nb t1 t2 t3 t1-0 t3-0 text) (b name))+ (defstrand init 2 (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3) (b b))+ (defstrand resp 2 (na na) (nb nb) (t1 t1-0) (t2 t2) (t3 t3-0) (b b))+ (precedes ((0 0) (1 0)) ((1 1) (0 1)))+ (non-orig (privk b))+ (uniq-orig na nb)+ (operation encryption-test (added-strand resp 2)+ (enc na nb b t2 (privk b)) (0 1))+ (traces+ ((send (cat nb t1))+ (recv (cat na nb b t3 (enc na nb b t2 (privk b)))))+ ((recv (cat nb t1-0))+ (send (cat na nb b t3-0 (enc na nb b t2 (privk b))))))+ (label 13)+ (parent 12)+ (unrealized)+ (shape)+ (satisfies (no (b b) (z (0 1))))+ (maps ((0) ((b b) (na na) (nb nb) (t1 t1) (t2 t2) (t3 t3))))+ (origs (na (1 1)) (nb (0 0))))++(comment "Nothing left to do")
tst/uo.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from uo.scm") (defprotocol uniq-orig basic
tst/wang-hash.tst view
@@ -1,6 +1,6 @@ (herald "Wang's Fair Exchange Protocol" (bound 10)) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from wang-hash.scm") (comment "Strand count bounded at 10")
tst/wang-key-hash.tst view
@@ -1,6 +1,6 @@ (herald "Wang's Fair Exchange Protocol" (bound 10)) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from wang-key-hash.scm") (comment "Strand count bounded at 10")
tst/weird.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from weird.scm") (defprotocol weird basic
tst/wide-mouth-frog-scyther.tst view
@@ -1,7 +1,7 @@ (herald "Wide-Mouth Frog Protocol from Scyther" (comment "This protocol has an infinite number of shapes")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from wide-mouth-frog-scyther.lsp") (defprotocol wide-mouth-frog basic
tst/wide-mouth-frog.tst view
@@ -1,7 +1,7 @@ (herald "Wide-Mouth Frog Protocol" (comment "This protocol has an infinite number of shapes")) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from wide-mouth-frog.lsp") (defprotocol wide-mouth-frog basic
tst/wonthull.tst view
@@ -1,6 +1,6 @@ (herald wonthull (bound 9)) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from wonthull.scm") (comment "Strand count bounded at 9")
tst/wonthull2.tst view
@@ -1,6 +1,6 @@ (herald wonthull2 (bound 9)) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from wonthull2.scm") (comment "Strand count bounded at 9")
tst/wonthull3.tst view
@@ -1,4 +1,4 @@-(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from wonthull3.scm") (defprotocol wonthull3 basic
tst/woolam.tst view
@@ -1,6 +1,6 @@ (herald "Woo-Lam Protocol") -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from woolam.scm") (defprotocol woolam basic
tst/yahalom-6.3.6.tst view
@@ -5,7 +5,7 @@ (url "http://www.eecs.umich.edu/acal/swerve/docs/49-1.pdf") (bound 15)) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from yahalom-6.3.6.scm") (comment "Strand count bounded at 15")
tst/yahalom.tst view
@@ -1,6 +1,6 @@ (herald "Yahalom Protocol Without Forwarding" (bound 15)) -(comment "CPSA 2.4.0")+(comment "CPSA 2.5.0") (comment "All input read from yahalom.scm") (comment "Strand count bounded at 15")