-- Verify.hs: OpenPGP (RFC4880) signature verification
-- Copyright © 2012-2016  Clint Adams
-- This software is released under the terms of the Expat license.
-- (See the LICENSE file).
module Data.Conduit.OpenPGP.Verify
  ( conduitVerify
  ) where

import Data.Conduit
import Data.Time.Clock (UTCTime)

import Codec.Encryption.OpenPGP.Internal (PktStreamContext(..), emptyPSC)
import Codec.Encryption.OpenPGP.Signatures (verifyAgainstKeyring, verifySigWith)
import Codec.Encryption.OpenPGP.Types
import qualified Data.Conduit.List as CL

conduitVerify ::
     Monad m
  => Keyring
  -> Maybe UTCTime
  -> ConduitT Pkt (Either String Verification) m ()
conduitVerify :: Keyring
-> Maybe UTCTime -> ConduitT Pkt (Either String Verification) m ()
conduitVerify kr :: Keyring
kr mt :: Maybe UTCTime
mt = (Pkt
 -> PktStreamContext
 -> (PktStreamContext, [Either String Verification]))
-> PktStreamContext
-> ConduitT Pkt (Either String Verification) m ()
forall (m :: * -> *) a accum b.
Monad m =>
(a -> accum -> (accum, [b])) -> accum -> ConduitT a b m ()
CL.concatMapAccum ((PktStreamContext
 -> Pkt -> (PktStreamContext, [Either String Verification]))
-> Pkt
-> PktStreamContext
-> (PktStreamContext, [Either String Verification])
forall a b c. (a -> b -> c) -> b -> a -> c
flip PktStreamContext
-> Pkt -> (PktStreamContext, [Either String Verification])
push) PktStreamContext
emptyPSC
  where
    push :: PktStreamContext
-> Pkt -> (PktStreamContext, [Either String Verification])
push state :: PktStreamContext
state ld :: Pkt
ld@LiteralDataPkt {} = (PktStreamContext
state {lastLD :: Pkt
lastLD = Pkt
ld}, [])
    push state :: PktStreamContext
state uid :: Pkt
uid@(UserIdPkt _) = (PktStreamContext
state {lastUIDorUAt :: Pkt
lastUIDorUAt = Pkt
uid}, [])
    push state :: PktStreamContext
state uat :: Pkt
uat@(UserAttributePkt _) = (PktStreamContext
state {lastUIDorUAt :: Pkt
lastUIDorUAt = Pkt
uat}, [])
    push state :: PktStreamContext
state pk :: Pkt
pk@(PublicKeyPkt _) = (PktStreamContext
state {lastPrimaryKey :: Pkt
lastPrimaryKey = Pkt
pk}, [])
    push state :: PktStreamContext
state pk :: Pkt
pk@(PublicSubkeyPkt _) = (PktStreamContext
state {lastSubkey :: Pkt
lastSubkey = Pkt
pk}, [])
    push state :: PktStreamContext
state sk :: Pkt
sk@(SecretKeyPkt _ _) = (PktStreamContext
state {lastPrimaryKey :: Pkt
lastPrimaryKey = Pkt
sk}, [])
    push state :: PktStreamContext
state sk :: Pkt
sk@(SecretSubkeyPkt _ _) = (PktStreamContext
state {lastSubkey :: Pkt
lastSubkey = Pkt
sk}, [])
    push state :: PktStreamContext
state sig :: Pkt
sig@(SignaturePkt SigV4 {}) =
      ( PktStreamContext
state {lastSig :: Pkt
lastSig = Pkt
sig}
      , [(Pkt -> Maybe UTCTime -> ByteString -> Either String Verification)
-> Pkt
-> PktStreamContext
-> Maybe UTCTime
-> Either String Verification
verifySigWith (Keyring
-> Pkt -> Maybe UTCTime -> ByteString -> Either String Verification
verifyAgainstKeyring Keyring
kr) Pkt
sig PktStreamContext
state Maybe UTCTime
mt])
    push state :: PktStreamContext
state (OnePassSignaturePkt _ _ _ _ _ False) = (PktStreamContext
state, [])
    push state :: PktStreamContext
state _ = (PktStreamContext
state, [])
    normLineEndings :: a -> a
normLineEndings = a -> a
forall a. a -> a
id -- FIXME