-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | The Disjunction Category Label Format -- -- The DC Label (DCLabel) library provides dynamic information -- flow control label format in the form of conjunctions of disjunctions -- of principals. Most code should import module DCLabel.Safe; -- trusted code should import DCLabel.TCB. The core functionality -- of the library is documented in DCLabel.Core, while the small -- EDSL used to create labels is documents in DCLabel.NanoEDSL. -- DCLabel was implemented by David Mazieres -- (http://www.scs.stanford.edu/~dm/), Deian Stefan -- (http://www.scs.stanford.edu/~deian/), and Alejandro Russo -- (http://www.cse.chalmers.se/~russo/). @package dclabel @version 0.0.2 -- | This module implements Disjunction Category labels. -- -- A DCLabel is a pair of secrecy and integrity category -- sets (of type Label). A category set (of type Conj) is a -- conjunction of categories (of type Disj). Each category, in -- turn, is a disjunction of Principals, where a Principal -- is just a String whose meaning is up to the application. -- -- A category imposes an information flow restriction. In the case of -- secrecy, a category restricts who can read, receive, or propagate the -- information, while in the case of integrity it restricts who can -- modify a piece of data. The principals constructing a category are -- said to own the category. -- -- For information to flow from a source labeled L_1 to a sink -- L_2, the restrictions imposed by the categories of -- L_2 must at least as restrictive as all the restrictions -- imposed by the categories of L_1 (hence the conjunction) in -- the case of secrecy, and at least as permissive in the case of -- integrity. More specifically, for information to flow from -- L_1 to L_2, the labels must satisfy the -- "can-flow-to" relation: L_1 ⊑ L_2. The ⊑ label check is -- implemented by the canflowto function. For labels -- L_1=<S_1, I_1>, L_2=<S_2, I_2> the -- can-flow-to relation is satisfied if the secrecy category set -- S_2 implies S_1 and I_1 -- implies I_2 (recall that a category set is a -- conjunction of disjunctions of principals). For example, <{[P_1 -- ⋁ P_2]},{}> ⊑ <{[P_1]},{}> because data that can be read -- by P_1 is more restricting than that readable by P_1 -- or P_2. Conversely, <{{},[P_1]}> ⊑ <{},[P_1 ⋁ -- P_2]},{}> because data vouched for by P_1 or -- P_2 is more permissive than just P_1 (note the same -- idea holds when writing to sinks with such labeling). -- -- A piece of a code running with a privilege object (of type -- TCBPriv), i.e., owning a Principal confers the right to -- modify labels by removing any secrecy categories containing -- that Principal and adding any integrity categories -- containing the Principal (hence the name disjunction -- categories: the category [P1 ⋁ P2] can be downgraded -- by either Principal P1 or P2). More -- specifically, privileges can be used to bypass information flow -- restrictions by using the more permissive "can-flow-to given -- permission" relation:⊑ᵨ. The label check function implementing this -- restriction is canflowto_p, taking an additional argument (of -- type TCBPriv). For example, if L_1=<{[P_1 ⋁ P_2] ⋀ -- [P_3]},{}>, and L_2=<{[P_1]},{}>, then L_1 -- ⋢ L_2, but given a privilege object corresponding to -- [P_3] the L_1 ⊑ᵨ L_2 holds. -- -- To construct DC labels and privilege objects the constructors exported -- by this module may be used, but we strongly suggest using -- DCLabel.NanoEDSL as exported by DCLabel.TCB and -- DCLabel.Safe. The former is to be used by trusted code only, -- while the latter module should be imported by untrusted code as it -- prevents the creation of arbitrary privileges. module DCLabel.Core -- | A category, i.e., disjunction, of Principals. The empty list -- '[]' corresponds to the disjunction of all principals. Conceptually, -- [] = [P_1 ⋁ P_2 ⋁ ...] newtype Disj MkDisj :: [Principal] -> Disj disj :: Disj -> [Principal] -- | A category set, i.e., a conjunction of disjunctions. The empty list -- '[]' corresponds to the single disjunction of all principals. In other -- words, conceptually, [] = {[P_1 ⋁ P_2 ⋁ ...]} newtype Conj MkConj :: [Disj] -> Conj conj :: Conj -> [Disj] -- | A label is a conjunction of disjunctions, where MkLabelAll is -- the constructor that is associated with the conjunction of all -- possible disjunctions. data Label MkLabelAll :: Label MkLabel :: Conj -> Label label :: Label -> Conj -- | A label without any disjunctions or conjunctions. This label, -- conceptually corresponds to the label consisting of a single category -- containing all principals. Conceptually, emptyLabel = <{[P_1 ⋁ -- P_2 ⋁ ...]}> emptyLabel :: Label -- | The dual of emptyLabel, allLabel consists of the -- conjunction of all possible disjunctions, i.e., it is the label that -- implies all other labels. Conceptually, allLabel = <{[P_1] ⋀ -- [P_2] ⋀ ...}> allLabel :: Label -- | Labels forma a partial order according to the ⊑ relation. -- Specifically, this means that for any two labels L_1 and -- L_2 there is a unique label L_3 = L_1 ⊔ L_2, known -- as the join, such that L_1 ⊑ L_3 and L_2 ⊑ -- L_3. Similarly, there is a unique label L_3' = L_1 ⊓ -- L_2, known as the meet, such that L_3 ⊑ L_1 and -- L_3 ⊑ L_2. This class defines a bounded lattice, which -- further requires the definition of the bottom ⊥ and top -- ⊤ elements of the lattice, such that ⊥ ⊑ L and L ⊑ ⊤ -- for any label L. class Eq a => Lattice a bottom :: Lattice a => a top :: Lattice a => a join :: Lattice a => a -> a -> a meet :: Lattice a => a -> a -> a canflowto :: Lattice a => a -> a -> Bool -- | Class used to reduce labels to a unique label normal form (LNF), which -- corresponds to conjunctive normal form of principals. We use this -- class to overload the reduce function used by the Label, -- DCLabel, etc. class ToLNF a toLNF :: ToLNF a => a -> a -- | A DCLabel is a pair of secrecy and integrity category sets, -- i.e., a pair of Labels. data DCLabel MkDCLabel :: Label -> Label -> DCLabel -- | Integrity category set. secrecy :: DCLabel -> Label -- | Secrecy category set. integrity :: DCLabel -> Label -- | Principal is a simple string representing a source of authority. Any -- piece of code can create principals, regarless of how untrusted it is. -- However, for principals to be used in integrity labels or be ignoerd a -- corresponding privilege (TCBPriv) must be created (by trusted -- code) or delegated. newtype Principal MkPrincipal :: String -> Principal name :: Principal -> String -- | Generates a principal from an string. principal :: String -> Principal -- | Privilege object is just a conjunction of disjunctions, i.e., a -- Label. A trusted privileged object must be introduced by -- trusted code, after which trusted privileged objects can be created by -- delegation. data TCBPriv MkTCBPriv :: Label -> TCBPriv priv :: TCBPriv -> Label -- | Untrusted privileged object, which can be converted to a -- TCBPriv with delegatePriv. type Priv = Label -- | Class extending Lattice, by allowing for the more relaxed label -- comparison canflowto_p. class Lattice a => RelaxedLattice a canflowto_p :: RelaxedLattice a => TCBPriv -> a -> a -> Bool -- | Privilege object corresponding to no privileges. noPriv :: TCBPriv -- | Privilege object corresponding to the "root", or all privileges. Any -- other privilege may be delegated using this privilege object and it -- must therefore not be exported to untrusted code. rootPrivTCB :: TCBPriv -- | Given trusted privilege and a "desired" untrusted privilege, return a -- trusted version of the untrusted privilege, if the provided (trusted) -- privilege implies it. delegatePriv :: TCBPriv -> Priv -> Maybe TCBPriv -- | This function creates any privilege object given an untrusted -- privilege Priv. Note that this function should not be exported -- to untrusted code. createPrivTCB :: Priv -> TCBPriv -- | Class used for checking if a computation can use a privilege in place -- of the other. This notion is similar to the DLM "can-act-for". class CanDelegate a b canDelegate :: CanDelegate a b => a -> b -> Bool -- | We say a TCBPriv privilege object owns a category when the -- privileges allow code to bypass restrictions implied by the category. -- This is the case if and only if the TCBPriv object contains one -- of the Principals in the Disj. This class is used to -- check ownership class Owns a owns :: Owns a => TCBPriv -> a -> Bool -- | Given two labels, take the union of the disjunctions, i.e., simply -- perform an "and". Note the new label is not necessarily in LNF. and_label :: Label -> Label -> Label -- | Given two labels, perform an "or". Note that the new label is not -- necessarily in LNF. or_label :: Label -> Label -> Label -- | Removes any duplicate principals from categories, and any duplicate -- categories from the label. To return a clean label, it sorts the label -- and removes empty disjunctions. cleanLabel :: Label -> Label -- | Determines if a label implies (in the logical sense) another label. In -- other words, d_1 ⋀ ... ⋀ d_n => d_1' ⋀ ... ⋀ d_n'. -- -- Properties: -- --
-- p1 = principal "p1" -- p2 = principal "p2" -- p3 = principal "p3" -- e1 = p1 .\/. p2 -- e2 = e1 .\/. "p4" ---- -- Similarly, the conjunction operator (./\.) is used to create -- category-sets from Principals, Strings, and -- conjunctive or disjunctive sub-expressions. For example: -- --
-- e3 = p1 .\/. p2 -- e4 = e1 ./\. "p4" ./\. p3 ---- -- Note that because a category consists of a disjunction of -- principals, and a category set is composed of the conjunction of -- categories, (.\/.) binds more tightly than (./\.). -- -- Given two Labels, one for secrecy and one for integrity, you -- can create a DCLabel with newDC. And, similarly, given a -- TCBPriv and Priv you can create a new minted privilege -- with newTCBPriv. -- -- Consider the following, example: -- --
-- l1 = "Alice" .\/. "Bob" ./\. "Carla"
-- l2 = "Alice" ./\. "Carla"
-- dc1 = newDC l1 l2
-- dc2 = newDC "Deian" "Alice"
-- pr = createPrivTCB $ newPriv ("Alice" ./\. "Carla")
--
--
-- where
--
-- dc1 = <{["Alice" ⋁ "Bob"] ⋀ ["Carla"]} , {["Alice"] ⋀
-- ["Carla"]}> dc2 = <{["Deian"]} , {["Alice"]}>canflowto dc1 dc2 = False
canflowto_p pr dc1 dc2 = True