{-|
Module      : Botan.Low.Verify
Description : Signature Verification
Copyright   : (c) Leo D, 2023
License     : BSD-3-Clause
Maintainer  : leo@apotheca.io
Stability   : experimental
Portability : POSIX
-}

module Botan.Low.PubKey.Verify
(

-- * Public key signature verification
  Verify(..)
, withVerify
, verifyCreate
, verifyDestroy
, verifyUpdate
, verifyFinish

) where

import qualified Data.ByteString as ByteString

import Botan.Bindings.PubKey.Verify

import Botan.Low.Error
import Botan.Low.Make
import Botan.Low.Prelude
import Botan.Low.RNG
import Botan.Low.PubKey
import Botan.Low.PubKey.Sign (SigningFlags(..))
import Botan.Low.Remake

-- /*
-- * Signature Verification
-- */

newtype Verify = MkVerify { Verify -> ForeignPtr BotanPKOpVerifyStruct
getVerifyForeignPtr :: ForeignPtr BotanPKOpVerifyStruct }

newVerify      :: BotanPKOpVerify -> IO Verify
withVerify     :: Verify -> (BotanPKOpVerify -> IO a) -> IO a
verifyDestroy  :: Verify -> IO ()
createVerify   :: (Ptr BotanPKOpVerify -> IO CInt) -> IO Verify
(BotanPKOpVerify -> IO Verify
newVerify, Verify -> (BotanPKOpVerify -> IO a) -> IO a
withVerify, Verify -> IO ()
verifyDestroy, (Ptr BotanPKOpVerify -> IO CInt) -> IO Verify
createVerify, (Ptr BotanPKOpVerify -> Ptr CSize -> IO CInt) -> IO [Verify]
_)
    = (Ptr BotanPKOpVerifyStruct -> BotanPKOpVerify)
-> (BotanPKOpVerify -> Ptr BotanPKOpVerifyStruct)
-> (ForeignPtr BotanPKOpVerifyStruct -> Verify)
-> (Verify -> ForeignPtr BotanPKOpVerifyStruct)
-> FinalizerPtr BotanPKOpVerifyStruct
-> (BotanPKOpVerify -> IO Verify,
    Verify -> (BotanPKOpVerify -> IO a) -> IO a, Verify -> IO (),
    (Ptr BotanPKOpVerify -> IO CInt) -> IO Verify,
    (Ptr BotanPKOpVerify -> Ptr CSize -> IO CInt) -> IO [Verify])
forall botan struct object a.
Storable botan =>
(Ptr struct -> botan)
-> (botan -> Ptr struct)
-> (ForeignPtr struct -> object)
-> (object -> ForeignPtr struct)
-> FinalizerPtr struct
-> (botan -> IO object, object -> (botan -> IO a) -> IO a,
    object -> IO (), (Ptr botan -> IO CInt) -> IO object,
    (Ptr botan -> Ptr CSize -> IO CInt) -> IO [object])
mkBindings
        Ptr BotanPKOpVerifyStruct -> BotanPKOpVerify
MkBotanPKOpVerify BotanPKOpVerify -> Ptr BotanPKOpVerifyStruct
runBotanPKOpVerify
        ForeignPtr BotanPKOpVerifyStruct -> Verify
MkVerify Verify -> ForeignPtr BotanPKOpVerifyStruct
getVerifyForeignPtr
        FinalizerPtr BotanPKOpVerifyStruct
botan_pk_op_verify_destroy

type VerifyAlgo = ByteString

verifyCreate
    :: PubKey       -- ^ __key__
    -> EMSAName     -- ^ __hash_and_padding__
    -> SigningFlags -- ^ __flags__
    -> IO Verify    -- ^ __op__
verifyCreate :: PubKey -> EMSAName -> SigningFlags -> IO Verify
verifyCreate PubKey
pk EMSAName
algo SigningFlags
flags =  PubKey -> (BotanPubKey -> IO Verify) -> IO Verify
forall a. PubKey -> (BotanPubKey -> IO a) -> IO a
withPubKey PubKey
pk ((BotanPubKey -> IO Verify) -> IO Verify)
-> (BotanPubKey -> IO Verify) -> IO Verify
forall a b. (a -> b) -> a -> b
$ \ BotanPubKey
pkPtr -> do
    EMSAName -> (Ptr CChar -> IO Verify) -> IO Verify
forall a. EMSAName -> (Ptr CChar -> IO a) -> IO a
asCString EMSAName
algo ((Ptr CChar -> IO Verify) -> IO Verify)
-> (Ptr CChar -> IO Verify) -> IO Verify
forall a b. (a -> b) -> a -> b
$ \ Ptr CChar
algoPtr -> do
        (Ptr BotanPKOpVerify -> IO CInt) -> IO Verify
createVerify ((Ptr BotanPKOpVerify -> IO CInt) -> IO Verify)
-> (Ptr BotanPKOpVerify -> IO CInt) -> IO Verify
forall a b. (a -> b) -> a -> b
$ \ Ptr BotanPKOpVerify
out -> Ptr BotanPKOpVerify
-> BotanPubKey -> ConstPtr CChar -> SigningFlags -> IO CInt
botan_pk_op_verify_create
            Ptr BotanPKOpVerify
out
            BotanPubKey
pkPtr
            (Ptr CChar -> ConstPtr CChar
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr CChar
algoPtr)
            SigningFlags
flags

-- WARNING: withFooInit-style limited lifetime functions moved to high-level botan
withVerifyCreate :: PubKey -> EMSAName -> SigningFlags -> (Verify -> IO a) -> IO a
withVerifyCreate :: forall a.
PubKey -> EMSAName -> SigningFlags -> (Verify -> IO a) -> IO a
withVerifyCreate = (PubKey -> EMSAName -> SigningFlags -> IO Verify)
-> (Verify -> IO ())
-> PubKey
-> EMSAName
-> SigningFlags
-> (Verify -> IO a)
-> IO a
forall x y z t a.
(x -> y -> z -> IO t)
-> (t -> IO ()) -> x -> y -> z -> (t -> IO a) -> IO a
mkWithTemp3 PubKey -> EMSAName -> SigningFlags -> IO Verify
verifyCreate Verify -> IO ()
verifyDestroy

verifyUpdate
    :: Verify       -- ^ __op__
    -> ByteString   -- ^ __in[]__
    -> IO ()
verifyUpdate :: Verify -> EMSAName -> IO ()
verifyUpdate = (forall a. Verify -> (BotanPKOpVerify -> IO a) -> IO a)
-> (BotanPKOpVerify -> ConstPtr Word8 -> CSize -> IO CInt)
-> Verify
-> EMSAName
-> IO ()
forall object botan.
(forall a. object -> (botan -> IO a) -> IO a)
-> (botan -> ConstPtr Word8 -> CSize -> IO CInt)
-> object
-> EMSAName
-> IO ()
mkWithObjectSetterCBytesLen Verify -> (BotanPKOpVerify -> IO a) -> IO a
forall a. Verify -> (BotanPKOpVerify -> IO a) -> IO a
withVerify BotanPKOpVerify -> ConstPtr Word8 -> CSize -> IO CInt
botan_pk_op_verify_update

-- TODO: Signature type
verifyFinish
    :: Verify       -- ^ __op__
    -> ByteString   -- ^ __sig[]__
    -> IO Bool
verifyFinish :: Verify -> EMSAName -> IO Bool
verifyFinish Verify
verify EMSAName
sig = Verify -> (BotanPKOpVerify -> IO Bool) -> IO Bool
forall a. Verify -> (BotanPKOpVerify -> IO a) -> IO a
withVerify Verify
verify ((BotanPKOpVerify -> IO Bool) -> IO Bool)
-> (BotanPKOpVerify -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \ BotanPKOpVerify
verifyPtr -> do
    EMSAName -> (Ptr Word8 -> CSize -> IO Bool) -> IO Bool
forall byte a. EMSAName -> (Ptr byte -> CSize -> IO a) -> IO a
asBytesLen EMSAName
sig ((Ptr Word8 -> CSize -> IO Bool) -> IO Bool)
-> (Ptr Word8 -> CSize -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
sigPtr CSize
sigLen -> do
        HasCallStack => IO CInt -> IO Bool
IO CInt -> IO Bool
throwBotanCatchingSuccess (IO CInt -> IO Bool) -> IO CInt -> IO Bool
forall a b. (a -> b) -> a -> b
$ BotanPKOpVerify -> ConstPtr Word8 -> CSize -> IO CInt
botan_pk_op_verify_finish
            BotanPKOpVerify
verifyPtr
            (Ptr Word8 -> ConstPtr Word8
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr Word8
sigPtr)
            CSize
sigLen