|
| 1 | +module PrettyIOSpecs.Gobra.BytesEncoding ( |
| 2 | + |
| 3 | + gobraBytesEncoding |
| 4 | + |
| 5 | + ) where |
| 6 | + |
| 7 | + |
| 8 | +import Prelude |
| 9 | +import qualified Data.Map as Map |
| 10 | +import qualified Data.Set as S |
| 11 | +import qualified Data.ByteString.Char8 as BC |
| 12 | + |
| 13 | +-- Tamarin prover imports |
| 14 | +import Text.PrettyPrint.Class |
| 15 | +import Term.Term.Raw |
| 16 | +import Term.Maude.Signature(MaudeSig, rrulesForMaudeSig, funSyms) |
| 17 | +import Term.Term.FunctionSymbols |
| 18 | +import Term.Builtin.Rules(RRule(..)) |
| 19 | +import Term.LTerm (frees) |
| 20 | +-- import Term.VTerm(constsVTerm) |
| 21 | +import Term.Builtin.Convenience(x1, x2, x3) |
| 22 | +import Theory.Model.Signature(_sigMaudeInfo) |
| 23 | +import qualified Theory as T |
| 24 | + |
| 25 | +-- Tamigloo imports |
| 26 | +-- ---- isabelle generated |
| 27 | +import GenericHelperFunctions(nub, splitAndGetFst, splitAndGetSnd) |
| 28 | +import qualified TamiglooDatatypes as TID |
| 29 | +-- ---- other Tamigloo modules |
| 30 | +import PrettyIOSpecs.Gobra.Utils |
| 31 | + |
| 32 | + |
| 33 | +-- The Byte encoding for verifast presents a different approach to print the byte function signatures and rrules |
| 34 | +-- Here this is achieved by changing the printers (e.g. ppFunSymB, ppRRuleB) while in the verifast case the funsyms and rrules are changed |
| 35 | + |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +gobraBytesEncoding :: Document d => Map.Map String String -> TID.Theory -> d |
| 40 | +gobraBytesEncoding config thy@(TID.Theory _thyName fsig _thyItems) = |
| 41 | + let |
| 42 | + -- assume maudeSig has been used appropriately to initialize funSyms |
| 43 | + sigMaude = ( _sigMaudeInfo fsig) |
| 44 | + in |
| 45 | + gobraHeader config "bytes" ["pub", "term"] ( |
| 46 | + domain "Bytes" ( |
| 47 | + baseEncoding $$ |
| 48 | + constEncoding thy $$ |
| 49 | + bytesFuncEncoding sigMaude $$ |
| 50 | + eqEncoding (read (config Map.! "triggers") :: TriggerSetting) sigMaude |
| 51 | + ) $$ text "\n\n\n" $$ |
| 52 | + domain "Gamma" ( |
| 53 | + gammaEncoding thy |
| 54 | + ) |
| 55 | + ) |
| 56 | + |
| 57 | + |
| 58 | +gammaEncoding :: Document d => TID.Theory -> d |
| 59 | +gammaEncoding thy@(TID.Theory _thyName _fsig _thyItems) = |
| 60 | + text "func gamma(Term) Bytes" $$ |
| 61 | + text "func oneTerm(Bytes) Term" $$ |
| 62 | + text "// totality" $$ |
| 63 | + axiom ( |
| 64 | + forallWithTriggerSetting |
| 65 | + All |
| 66 | + (text "b Bytes") |
| 67 | + [text "oneTerm(b)"] |
| 68 | + (text "gamma(oneTerm(b)) == b") |
| 69 | + ) $$ text "\n" $$ |
| 70 | + text "// homomorphism" $$ |
| 71 | + axiom ( |
| 72 | + gammaHomomorphism thy $$ |
| 73 | + text "// TODO: Add homomorphism axiom for constructors you added yourself e.g." $$ |
| 74 | + text "// &&" $$ |
| 75 | + text "// (forall s string :: {gamma(msg(s))} gamma(msg(s)) == msgB(s))" |
| 76 | + ) |
| 77 | + |
| 78 | +gammaHomomorphism :: Document d => TID.Theory -> d |
| 79 | +gammaHomomorphism thy@(TID.Theory _thyName fsig _thyItems) = |
| 80 | + let |
| 81 | + -- get function signatures from Maude signature |
| 82 | + sigMaude = ( _sigMaudeInfo fsig) |
| 83 | + funcSyms = S.toList (funSyms sigMaude) |
| 84 | + in |
| 85 | + (vcat $ punctuate (text " &&") $ (gammaConstants thy) ++ (map homomorphismSingleFunc funcSyms)) $$ text "\n" |
| 86 | + |
| 87 | +homomorphismSingleFunc :: Document d => FunSym -> d |
| 88 | +homomorphismSingleFunc fs = |
| 89 | + let |
| 90 | + args = map (TID.varToVTerm . TID.createLVarFromName) (auxArgs fs) |
| 91 | + termFuncApp = termViewToTerm (FApp fs args) |
| 92 | + termFuncAppDoc = text (prettyGobraLNTerm True termFuncApp) |
| 93 | + gammaArgsDoc = map (\t -> text $ functionApp "gamma" [t]) (auxArgs fs) |
| 94 | + gammaApp = functionAppDoc (text "gamma") [termFuncAppDoc] |
| 95 | + byteFuncAppDoc = functionAppDoc (text $ funSymName fs ++ "B") gammaArgsDoc |
| 96 | + body = gammaApp <> text " == " <> byteFuncAppDoc |
| 97 | + in |
| 98 | + text "(" <> |
| 99 | + (if length (auxArgs fs) > 0 |
| 100 | + then |
| 101 | + forallWithTriggerSettingInline |
| 102 | + All |
| 103 | + ((sepTerms $ map text (auxArgs fs)) <> text " Term") |
| 104 | + [gammaApp] |
| 105 | + body |
| 106 | + else |
| 107 | + body) |
| 108 | + <> text ")" |
| 109 | + where |
| 110 | + auxArgs :: FunSym -> [String] |
| 111 | + auxArgs (NoEq (_, (ar, _))) = (convenienceNames ar "t") |
| 112 | + auxArgs _ = (convenienceNames 2 "t") |
| 113 | + funSymName :: FunSym -> String |
| 114 | + funSymName (NoEq (f, (_, _))) = reservedGobraWords (BC.unpack f) |
| 115 | + funSymName (AC o) = reservedGobraWords (show o) |
| 116 | + funSymName (C EMap) = reservedGobraWords (BC.unpack emapSymString) |
| 117 | + funSymName (List) = "listB" |
| 118 | + |
| 119 | +gammaConstants :: Document d => TID.Theory -> [d] |
| 120 | +gammaConstants thy = |
| 121 | + let |
| 122 | + constants = nub (TID.extractConsts thy) |
| 123 | + in |
| 124 | + map (singleGammaConst . makeNameConst) constants |
| 125 | + where |
| 126 | + singleGammaConst :: Document d => String -> d |
| 127 | + singleGammaConst constName = |
| 128 | + let |
| 129 | + gammaApp = functionAppDoc (text "gamma") [text "pubTerm(" <> text (reservedGobraWords constName) <> text "())"] |
| 130 | + constant = functionAppDoc (text (removeConstantSuffix (reservedGobraWords constName) ++ "B")) [] |
| 131 | + in |
| 132 | + parens (gammaApp <> text " == " <> constant) |
| 133 | + |
| 134 | +baseEncoding :: Document d => d |
| 135 | +baseEncoding = |
| 136 | + text "// TODO: Add constructors from other types e.g." $$ |
| 137 | + text "// func msgB(string) Bytes" $$ text "\n" |
| 138 | + |
| 139 | +bytesFuncEncoding :: Document d => MaudeSig -> d |
| 140 | +bytesFuncEncoding sigMaude = |
| 141 | + let |
| 142 | + -- get function signatures from Maude signature |
| 143 | + funcSyms = S.toList (funSyms sigMaude) |
| 144 | + in |
| 145 | + text "// function declarations" $$ |
| 146 | + (vcat $ map (ppFunSymB "Bytes") funcSyms) $$ text "\n" |
| 147 | + |
| 148 | +eqEncoding :: Document d => TriggerSetting -> MaudeSig -> d |
| 149 | +eqEncoding triggerSetting sigMaude = |
| 150 | + let |
| 151 | + rrules = S.toList (rrulesForMaudeSig sigMaude) |
| 152 | + in |
| 153 | + text "// function equalities" $$ |
| 154 | + (vcat $ punctuate (text "\n") $ map (ppRRuleB triggerSetting "Bytes") rrules) |
| 155 | + |
| 156 | + |
| 157 | +constEncoding :: Document d => TID.Theory -> d |
| 158 | +constEncoding thy = |
| 159 | + let |
| 160 | + constants = nub (TID.extractConsts thy) |
| 161 | + in |
| 162 | + text "// constants"$$ |
| 163 | + (vcat $ |
| 164 | + map (constFuncDef . makeNameConst) constants) <> text "\n" |
| 165 | + where |
| 166 | + constFuncDef :: Document d => String -> d |
| 167 | + constFuncDef constName = |
| 168 | + text $ functionDef (removeConstantSuffix (reservedGobraWords constName) ++ "B") [] "Bytes" |
| 169 | + |
| 170 | +removeConstantSuffix :: String -> String |
| 171 | +removeConstantSuffix s = |
| 172 | + if (reverse . splitAndGetFst . reverse) s == "pub" |
| 173 | + then (reverse . splitAndGetSnd . reverse) s |
| 174 | + else s |
| 175 | + |
| 176 | +{- ---- ---- associativity encoding -} |
| 177 | +assocEncoding :: Document d => FunSym -> d |
| 178 | +assocEncoding acSym@(AC _) = ppRRuleB Lhs "Bytes" (rruleAssoc acSym) |
| 179 | + where |
| 180 | + rruleAssoc :: FunSym -> RRule T.LNTerm |
| 181 | + rruleAssoc acOp = auxFapp acOp [x1, auxFapp acOp [x2, x3]] |
| 182 | + `RRule` auxFapp acOp [auxFapp acOp [x1, x2], x3] |
| 183 | + auxFapp :: FunSym -> [T.LNTerm] -> T.LNTerm |
| 184 | + auxFapp fs ts = termViewToTerm (FApp fs ts) |
| 185 | +assocEncoding _ = error "assocEncoding called with non-ac function symbol" |
| 186 | + |
| 187 | +{- ---- ---- commutativity encoding -} |
| 188 | +commEncoding :: Document d => FunSym -> d |
| 189 | +commEncoding acSym@(AC _) = ppRRuleB Lhs "Bytes" (rruleComm acSym) |
| 190 | + where |
| 191 | + rruleComm :: FunSym -> RRule T.LNTerm |
| 192 | + rruleComm acOp = termViewToTerm (FApp acOp [x1, x2]) |
| 193 | + `RRule` termViewToTerm (FApp acOp [x2, x1]) |
| 194 | +commEncoding _ = error "commEncoding called with non-ac function symbol" |
| 195 | + |
| 196 | + |
| 197 | + |
| 198 | + |
| 199 | +ppFunSymB :: Document d => String -> FunSym -> d |
| 200 | +ppFunSymB typeId (NoEq (f, (ar, _))) = |
| 201 | + -- we do not make a distinction between private and public since we don't consider the adversary |
| 202 | + let |
| 203 | + args = map (++ " " ++ typeId) (convenienceNames ar "t") |
| 204 | + in |
| 205 | + text $ functionDef (reservedGobraWords (BC.unpack f) ++ "B") args typeId |
| 206 | +ppFunSymB typeId (AC o) = |
| 207 | + -- AC function symbols are made to be binary |
| 208 | + -- This needs to happen in function declaration and application |
| 209 | + (text $ functionDef (reservedGobraWords (show o) ++ "B") ["x " ++ typeId, "y " ++ typeId] typeId) $$ |
| 210 | + text ("// " ++ (reservedGobraWords (show o) ++ "B") ++ " is associative") $$ |
| 211 | + assocEncoding (AC o) $$ |
| 212 | + text ("// " ++ (reservedGobraWords (show o) ++ "B") ++ " is commutative") $$ |
| 213 | + commEncoding (AC o) $$ text "\n" |
| 214 | +ppFunSymB typeId (C EMap) = -- TODO not sure if we should print emapSymString or EMap |
| 215 | + text $ functionDef (reservedGobraWords (BC.unpack emapSymString) ++ "B") ["x " ++ typeId, "y " ++ typeId] typeId |
| 216 | +ppFunSymB typeId (List) = -- TODO not sure about this one, but does not seem to be used anyway |
| 217 | + text $ functionDef "listB" ["l seq[" ++ typeId ++ "]"] typeId |
| 218 | + |
| 219 | + |
| 220 | + |
| 221 | +ppRRuleB :: Document d => TriggerSetting -> String -> T.RRule T.LNTerm -> d |
| 222 | +ppRRuleB triggerSetting typeId rr@(T.RRule lhs rhs) = |
| 223 | + let |
| 224 | + trigger = (auxTrigger lhs) ++ (auxTrigger rhs) |
| 225 | + body = text (prettyGobraLNTermB True lhs) <> text " == " <> text (prettyGobraLNTermB True rhs) |
| 226 | + vars = frees rr |
| 227 | + doc_vars = sepTerms (map (text . prettyGobraLNTermB True . TID.varToVTerm) vars) <> text (" " ++ typeId) |
| 228 | + in |
| 229 | + if null vars |
| 230 | + then axiom body |
| 231 | + else axiom (forallWithTriggerSetting triggerSetting doc_vars trigger body) |
| 232 | + where |
| 233 | + auxTrigger :: Document d => T.LNTerm -> [d] |
| 234 | + auxTrigger t = case viewTerm t of |
| 235 | + (FApp _ (_:_)) -> [text $ prettyGobraLNTermB True t] |
| 236 | + _ -> [emptyDoc] |
| 237 | + |
| 238 | + |
| 239 | +prettyGobraLNTermB :: Bool -> T.LNTerm -> String |
| 240 | +prettyGobraLNTermB wrap = prettyGobraTermB (prettyLit wrap) |
| 241 | + |
| 242 | +-- | Pretty print a term. |
| 243 | +prettyGobraTermB :: Show l => (l -> String) -> Term l -> String |
| 244 | +prettyGobraTermB ppLit = ppTerm |
| 245 | + where |
| 246 | + ppTerm t = case viewTerm t of |
| 247 | + Lit l -> ppLit l |
| 248 | + FApp (AC o) ts -> auxAC (AC o) ts |
| 249 | + FApp (NoEq (f, _)) ts -> ppFunBC f ts |
| 250 | + FApp (C EMap) ts -> ppFunBC emapSymString ts |
| 251 | + FApp List ts -> ppFun "list" ts |
| 252 | + |
| 253 | + ppFunBC f ts = ppFun (BC.unpack f) ts |
| 254 | + |
| 255 | + ppFun f ts = |
| 256 | + (reservedGobraWords f) ++ "B" ++"(" ++ joinString ", " (map ppTerm ts) ++ ")" |
| 257 | + |
| 258 | + auxAC (AC o) ts = case ts of |
| 259 | + [a] -> ppTerm a |
| 260 | + [a, b] -> ppFun (show o) [a, b] |
| 261 | + x:xs -> ppFun (show o) [x, termViewToTerm (FApp (AC o) xs)] |
| 262 | + _ -> error "AC op cannot have empty args" |
| 263 | + auxAC _ _ = error "auxAC called with non-ac function symbol" |
| 264 | + |
| 265 | + |
0 commit comments