-- 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.4 -- | This module implements Disjunction Category Labels. -- -- A DCLabel is a pair of secrecy and integrity category -- sets or components, of type Component. Each component is simply -- a set of clauses in propositional logic (without negation). A -- component can either correspond to the term MkComponentAll, -- representing falsehood, or a set of categories (clauses): (of type -- Conj) corresponding to the conjunction of ategories (of type -- Disj). Each category, in turn, is a disjunction of -- Principals, where a Principal is just a -- ByteString 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 ⋁ ...]} Logically '[]' -- = True. newtype Conj MkConj :: [Disj] -> Conj conj :: Conj -> [Disj] -- | A components is a conjunction of disjunctions, where -- MkComponentAll is the constructor that is associated with the -- logical False. data Component MkComponentAll :: Component MkComponent :: Conj -> Component component :: Component -> Conj -- | A component without any disjunctions or conjunctions. This component, -- conceptually corresponds to the label consisting of a single category -- containing all principals. Conceptually (in a closed-world system), -- emptyComponent = <{[P_1 ⋁ P_2 ⋁ ...]}>. Logically, of -- course, this is equivalent to True. emptyComponent :: Component -- | The dual of emptyComponent, allComponent consists of the -- conjunction of all possible disjunctions, i.e., it is the label that -- implies all other labels. Conceptually (in a closed-world system), -- allComponent = <{[P_1] ⋀ [P_2] ⋀ ...}> Logically, of -- course, this is equivalent to False. allComponent :: Component -- | Labels form 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 and components to 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 -- Component, 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 Components. data DCLabel MkDCLabel :: Component -> Component -> DCLabel -- | Integrity category set. secrecy :: DCLabel -> Component -- | Secrecy category set. integrity :: DCLabel -> Component -- | 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 components or be -- ignoerd a corresponding privilege (TCBPriv) must be created (by -- trusted code) or delegated. newtype Principal MkPrincipal :: ByteString -> Principal name :: Principal -> ByteString -- | Generates a principal from an string. principal :: ByteString -> Principal -- | Privilege object is just a conjunction of disjunctions, i.e., -- Component. A trusted privileged object must be introduced by -- trusted code, after which trusted privileged objects can be created by -- delegation. data TCBPriv MkTCBPriv :: Component -> TCBPriv priv :: TCBPriv -> Component -- | Untrusted privileged object, which can be converted to a -- TCBPriv with delegatePriv. type Priv = Component -- | 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 components, take the union of the disjunctions, i.e., simply -- perform an "and". Note the new component is not necessarily in LNF. and_component :: Component -> Component -> Component -- | Given two components, perform an "or". Note that the new component is -- not necessarily in LNF. or_component :: Component -> Component -> Component -- | Removes any duplicate principals from categories, and any duplicate -- categories from the component. To return a clean component, it sorts -- the component and removes empty disjunctions. cleanComponent :: Component -> Component -- | Determines if a component logically implies another component. 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 Components, 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