-- SPDX-FileCopyrightText: 2020 Serokell
--
-- SPDX-License-Identifier: MPL-2.0

-- | @crypto_verify_*@
module Crypto.Internal.Verify
  ( verifyBytes32
  ) where

import Data.ByteArray (ByteArrayAccess, withByteArray)
import Data.ByteArray.Sized (SizedByteArray)

import qualified Libsodium as Na


-- | Compare two byte arrays of length 32.
verifyBytes32
  :: ( ByteArrayAccess ba1
     , ByteArrayAccess ba2
     )
  => SizedByteArray 32 ba1  -- ^ First byte array
  -> SizedByteArray 32 ba2  -- ^ Second byte array
  -> IO Bool
verifyBytes32 :: SizedByteArray 32 ba1 -> SizedByteArray 32 ba2 -> IO Bool
verifyBytes32 SizedByteArray 32 ba1
bytes1 SizedByteArray 32 ba2
bytes2 =
  SizedByteArray 32 ba1 -> (Ptr CUChar -> IO Bool) -> IO Bool
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray SizedByteArray 32 ba1
bytes1 ((Ptr CUChar -> IO Bool) -> IO Bool)
-> (Ptr CUChar -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
ptr1 ->
  SizedByteArray 32 ba2 -> (Ptr CUChar -> IO Bool) -> IO Bool
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray SizedByteArray 32 ba2
bytes2 ((Ptr CUChar -> IO Bool) -> IO Bool)
-> (Ptr CUChar -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
ptr2 -> do
    -- TODO: I have no idea what I am doing
    --
    -- - Sodium also checks that pointers are different?
    -- - This kind of double comparison was added in
    --   c5a9d46386f917aa0ff1bfb711450f9af1d79a17
    --   (why?)
    CInt
res1 <- Ptr CUChar -> Ptr CUChar -> IO CInt
forall k1 k2 (x :: k1) (y :: k2).
Ptr CUChar -> Ptr CUChar -> IO CInt
Na.crypto_verify_32 Ptr CUChar
ptr1 Ptr CUChar
ptr2
    CInt
res2 <- Ptr CUChar -> Ptr CUChar -> (Any ::: CSize) -> IO CInt
forall k1 k2 k3 (b1 :: k1) a (b2 :: k2) (len :: k3).
(b1 ::: Ptr a) -> (b1 ::: Ptr a) -> (Any ::: CSize) -> IO CInt
Na.sodium_memcmp Ptr CUChar
ptr2 Ptr CUChar
ptr1 Any ::: CSize
32
    Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ CInt
res1 CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0 Bool -> Bool -> Bool
&& CInt
res2 CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0