-- 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 :: forall (m :: * -> *).
Monad m =>
Keyring
-> Maybe UTCTime -> ConduitT Pkt (Either String Verification) m ()
conduitVerify Keyring
kr 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 PktStreamContext
state ld :: Pkt
ld@LiteralDataPkt {} = (PktStreamContext
state {lastLD :: Pkt
lastLD = Pkt
ld}, [])
    push PktStreamContext
state uid :: Pkt
uid@(UserIdPkt Text
_) = (PktStreamContext
state {lastUIDorUAt :: Pkt
lastUIDorUAt = Pkt
uid}, [])
    push PktStreamContext
state uat :: Pkt
uat@(UserAttributePkt [UserAttrSubPacket]
_) = (PktStreamContext
state {lastUIDorUAt :: Pkt
lastUIDorUAt = Pkt
uat}, [])
    push PktStreamContext
state pk :: Pkt
pk@(PublicKeyPkt PKPayload
_) = (PktStreamContext
state {lastPrimaryKey :: Pkt
lastPrimaryKey = Pkt
pk}, [])
    push PktStreamContext
state pk :: Pkt
pk@(PublicSubkeyPkt PKPayload
_) = (PktStreamContext
state {lastSubkey :: Pkt
lastSubkey = Pkt
pk}, [])
    push PktStreamContext
state sk :: Pkt
sk@(SecretKeyPkt PKPayload
_ SKAddendum
_) = (PktStreamContext
state {lastPrimaryKey :: Pkt
lastPrimaryKey = Pkt
sk}, [])
    push PktStreamContext
state sk :: Pkt
sk@(SecretSubkeyPkt PKPayload
_ SKAddendum
_) = (PktStreamContext
state {lastSubkey :: Pkt
lastSubkey = Pkt
sk}, [])
    push 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 PktStreamContext
state (OnePassSignaturePkt PacketVersion
_ SigType
_ HashAlgorithm
_ PubKeyAlgorithm
_ EightOctetKeyId
_ Bool
False) = (PktStreamContext
state, [])
    push PktStreamContext
state Pkt
_ = (PktStreamContext
state, [])
    normLineEndings :: a -> a
normLineEndings = a -> a
forall a. a -> a
id -- FIXME