{-# LANGUAGE StaticPointers #-}

module Hackage.Security.Trusted (
    module Hackage.Security.Trusted.TCB
    -- * Derived functions
  , (<$$>)
    -- ** Role verification
  , VerifyRole(..)
    -- ** File info verification
  , trustedFileInfoEqual
  ) where

import Prelude
import Data.Function (on)
import Data.Time
import Hackage.Security.TUF
import Hackage.Security.Trusted.TCB hiding (DeclareTrusted)

{-------------------------------------------------------------------------------
  Combinators on trusted values
-------------------------------------------------------------------------------}

-- | Apply a static function to a trusted argument
(<$$>) :: StaticPtr (a -> b) -> Trusted a -> Trusted b
<$$> :: forall a b. StaticPtr (a -> b) -> Trusted a -> Trusted b
(<$$>) = Trusted (a -> b) -> Trusted a -> Trusted b
forall a b. Trusted (a -> b) -> Trusted a -> Trusted b
trustApply (Trusted (a -> b) -> Trusted a -> Trusted b)
-> (StaticPtr (a -> b) -> Trusted (a -> b))
-> StaticPtr (a -> b)
-> Trusted a
-> Trusted b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StaticPtr (a -> b) -> Trusted (a -> b)
forall a. StaticPtr a -> Trusted a
trustStatic

{-------------------------------------------------------------------------------
  Role verification
-------------------------------------------------------------------------------}

class VerifyRole a where
  verifyRole :: Trusted Root      -- ^ Root data
             -> TargetPath        -- ^ Source (for error messages)
             -> Maybe FileVersion -- ^ Previous version (if available)
             -> Maybe UTCTime     -- ^ Time now (if checking expiry)
             -> Signed a          -- ^ Mirrors to verify
             -> Either VerificationError (SignaturesVerified a)

instance VerifyRole Root where
  verifyRole :: Trusted Root
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Root
-> Either VerificationError (SignaturesVerified Root)
verifyRole = Trusted (RoleSpec Root)
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Root
-> Either VerificationError (SignaturesVerified Root)
forall a.
HasHeader a =>
Trusted (RoleSpec a)
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed a
-> Either VerificationError (SignaturesVerified a)
verifyRole' (Trusted (RoleSpec Root)
 -> TargetPath
 -> Maybe FileVersion
 -> Maybe UTCTime
 -> Signed Root
 -> Either VerificationError (SignaturesVerified Root))
-> (Trusted Root -> Trusted (RoleSpec Root))
-> Trusted Root
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Root
-> Either VerificationError (SignaturesVerified Root)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (static (RootRoles -> RoleSpec Root
rootRolesRoot (RootRoles -> RoleSpec Root)
-> (Root -> RootRoles) -> Root -> RoleSpec Root
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Root -> RootRoles
rootRoles) StaticPtr (Root -> RoleSpec Root)
-> Trusted Root -> Trusted (RoleSpec Root)
forall a b. StaticPtr (a -> b) -> Trusted a -> Trusted b
<$$>)

instance VerifyRole Timestamp where
  verifyRole :: Trusted Root
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Timestamp
-> Either VerificationError (SignaturesVerified Timestamp)
verifyRole = Trusted (RoleSpec Timestamp)
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Timestamp
-> Either VerificationError (SignaturesVerified Timestamp)
forall a.
HasHeader a =>
Trusted (RoleSpec a)
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed a
-> Either VerificationError (SignaturesVerified a)
verifyRole' (Trusted (RoleSpec Timestamp)
 -> TargetPath
 -> Maybe FileVersion
 -> Maybe UTCTime
 -> Signed Timestamp
 -> Either VerificationError (SignaturesVerified Timestamp))
-> (Trusted Root -> Trusted (RoleSpec Timestamp))
-> Trusted Root
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Timestamp
-> Either VerificationError (SignaturesVerified Timestamp)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (static (RootRoles -> RoleSpec Timestamp
rootRolesTimestamp (RootRoles -> RoleSpec Timestamp)
-> (Root -> RootRoles) -> Root -> RoleSpec Timestamp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Root -> RootRoles
rootRoles) StaticPtr (Root -> RoleSpec Timestamp)
-> Trusted Root -> Trusted (RoleSpec Timestamp)
forall a b. StaticPtr (a -> b) -> Trusted a -> Trusted b
<$$>)

instance VerifyRole Snapshot where
  verifyRole :: Trusted Root
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Snapshot
-> Either VerificationError (SignaturesVerified Snapshot)
verifyRole = Trusted (RoleSpec Snapshot)
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Snapshot
-> Either VerificationError (SignaturesVerified Snapshot)
forall a.
HasHeader a =>
Trusted (RoleSpec a)
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed a
-> Either VerificationError (SignaturesVerified a)
verifyRole' (Trusted (RoleSpec Snapshot)
 -> TargetPath
 -> Maybe FileVersion
 -> Maybe UTCTime
 -> Signed Snapshot
 -> Either VerificationError (SignaturesVerified Snapshot))
-> (Trusted Root -> Trusted (RoleSpec Snapshot))
-> Trusted Root
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Snapshot
-> Either VerificationError (SignaturesVerified Snapshot)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (static (RootRoles -> RoleSpec Snapshot
rootRolesSnapshot (RootRoles -> RoleSpec Snapshot)
-> (Root -> RootRoles) -> Root -> RoleSpec Snapshot
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Root -> RootRoles
rootRoles) StaticPtr (Root -> RoleSpec Snapshot)
-> Trusted Root -> Trusted (RoleSpec Snapshot)
forall a b. StaticPtr (a -> b) -> Trusted a -> Trusted b
<$$>)

instance VerifyRole Mirrors where
  verifyRole :: Trusted Root
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Mirrors
-> Either VerificationError (SignaturesVerified Mirrors)
verifyRole = Trusted (RoleSpec Mirrors)
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Mirrors
-> Either VerificationError (SignaturesVerified Mirrors)
forall a.
HasHeader a =>
Trusted (RoleSpec a)
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed a
-> Either VerificationError (SignaturesVerified a)
verifyRole' (Trusted (RoleSpec Mirrors)
 -> TargetPath
 -> Maybe FileVersion
 -> Maybe UTCTime
 -> Signed Mirrors
 -> Either VerificationError (SignaturesVerified Mirrors))
-> (Trusted Root -> Trusted (RoleSpec Mirrors))
-> Trusted Root
-> TargetPath
-> Maybe FileVersion
-> Maybe UTCTime
-> Signed Mirrors
-> Either VerificationError (SignaturesVerified Mirrors)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (static (RootRoles -> RoleSpec Mirrors
rootRolesMirrors (RootRoles -> RoleSpec Mirrors)
-> (Root -> RootRoles) -> Root -> RoleSpec Mirrors
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Root -> RootRoles
rootRoles) StaticPtr (Root -> RoleSpec Mirrors)
-> Trusted Root -> Trusted (RoleSpec Mirrors)
forall a b. StaticPtr (a -> b) -> Trusted a -> Trusted b
<$$>)

{-------------------------------------------------------------------------------
  File info verification
-------------------------------------------------------------------------------}

-- | Variation on 'knownFileInfoEqual' for 'Trusted' 'FileInfo'
trustedFileInfoEqual :: Trusted FileInfo -> Trusted FileInfo -> Bool
trustedFileInfoEqual :: Trusted FileInfo -> Trusted FileInfo -> Bool
trustedFileInfoEqual = FileInfo -> FileInfo -> Bool
knownFileInfoEqual (FileInfo -> FileInfo -> Bool)
-> (Trusted FileInfo -> FileInfo)
-> Trusted FileInfo
-> Trusted FileInfo
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Trusted FileInfo -> FileInfo
forall a. Trusted a -> a
trusted