###### tags: `chalmers`
# Security
We divided the code for our secure interpreter in two module files plus a testing one:
- `Security.hs` which turned out to be so short it's easier to just copy-paste it, rather than trying to explain what it does:
```haskell=
module Security where
-- * Task 1
data Sensitivity = Secret | Public
deriving (Show, Eq, Ord)
instance Semigroup Sensitivity where
Public <> Public = Public
_ <> _ = Secret
instance Monoid Sensitivity where
mempty = Public
-- * Task 2
data Labeled a = LV Sensitivity a
deriving (Show, Eq)
instance (Ord a) => Ord (Labeled a) where
(LV _ a) <= (LV _ b) = a <= b
```
> NOTE: even if we were asked to instantiate `Monoid Semigroup` by defining `mappend` we decided to use the `<>` operator of the `Semigroup` class, instead. If we are not mistaken, this has been the best practice since `mappend` has become obsolete in the versions of Haskell following after base-4.11.0.0 [[docs](https://hackage.haskell.org/package/base-4.14.1.0/docs/Prelude.html#v:mappend)].
- `Basic.hs` which imports `Security` and in which the actual interpreter is defined
and
- `Test.hs` for automatic testing.
In `Basic.hs` we define the types `Expr`, `Name`, `Value`, `Env`, `Ptr` and `Store` accordingly:
```haskell=18
data Expr = Lit Integer
| Expr :+: Expr
| Var Name
| Let Name Expr Expr
| NewRef Expr
| Deref Expr
| Expr := Expr
| Secr Expr
deriving (Show)
-- | Preliminaries for (immutable) local bindings
type Name = String
type Value = Integer
-- | An environment maps variables to values.
type Env = Map Name (Labeled Value)
-- | Preliminaries for mutuable references
type Ptr = Value
-- ^ dangerous language: any 'Value' can be used as a 'Ptr'
-- | We need to keep track of the store containing the values of
-- our references. We also remember the next unused pointer.
data Store = Store { nextPtr :: Ptr
, heap :: Map Ptr (Labeled Value)
}
```
The only changes from the code skeleton is that the environment `Env` as well as `heap` in `Store` now maps to `Labeled Value` to allow for security. We also added the `Secr` constructor for `Expr` which is used to create secret values.
The rest of the code was modified to work with `Labeled Value` instead of `Value`, which did not make it all that different. One interesting thing to point out however is how we handled the security level of references. Our heap is a map from `Ptr` to `Labeled Value`. The security level of the value cannot be changed after the reference has been created. If one tries to write a public value to a secret reference, the value in the reference becomes secret. If one tries to write a secret value to a public reference, the interpreter throws an error. Below is the code for the assignment operator of our language:
```haskell=100
(=:) :: MonadState Store m => Ptr -> Labeled Value
-> m (Labeled Value)
(=:) ptr (LV p v) = do
store <- get
let h = heap store
case Map.lookup ptr h of
Nothing -> fail $
"Segmentation fault: "++show ptr++" is not bound"
Just (LV p' v') -> if p < p'
then fail $
"Security fault: " ++
"Cannot write a secret value to a public location"
else do
let heap' = Map.adjust (const (LV p' v)) ptr (heap store)
put (store {heap = heap'})
return (LV p' v)
```