{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}

-- |
-- Module      : Crypto.Saltine.Core.AEAD
-- Copyright   : (c) Thomas DuBuisson 2017
-- License     : MIT
--
-- Maintainer  : me@jspha.com
-- Stability   : experimental
-- Portability : non-portable
--
-- Secret-key authenticated encryption with additional data (AEAD):
-- "Crypto.Saltine.Core.AEAD"
--
-- The 'aead' function encrypts and authenticates a message
-- 'ByteString' and additional authenticated data 'ByteString'
-- using a secret key and a nonce. The 'aeadOpen'
-- function verifies and decrypts a ciphertext 'ByteString' using a
-- secret key and a nonce. If the ciphertext fails validation,
-- 'aeadOpen' returns 'Nothing'.
--
-- The "Crypto.Saltine.Core.AEAD" module is designed to meet
-- the standard notions of privacy and authenticity for a secret-key
-- authenticated-encryption scheme using nonces. For formal
-- definitions see, e.g., Bellare and Namprempre, "Authenticated
-- encryption: relations among notions and analysis of the generic
-- composition paradigm," Lecture Notes in Computer Science 1976
-- (2000), 531–545, <http://www-cse.ucsd.edu/~mihir/papers/oem.html>.
--
-- Note that the length is not hidden. Note also that it is the
-- caller's responsibility to ensure the uniqueness of nonces—for
-- example, by using nonce 1 for the first message, nonce 2 for the
-- second message, etc. Nonces are long enough that randomly generated
-- nonces have negligible risk of collision.

module Crypto.Saltine.Core.AEAD (
  Key, Nonce,
  aead, aeadOpen,
  aeadDetached, aeadOpenDetached,
  newKey, newNonce
  ) where

import           Crypto.Saltine.Class
import           Crypto.Saltine.Internal.Util
import qualified Crypto.Saltine.Internal.ByteSizes as Bytes

import           Control.Applicative
import           Foreign.C
import           Foreign.Ptr
import qualified Data.ByteString                   as S
import           Data.ByteString                     (ByteString)
import           Data.Hashable (Hashable)
import           Data.Data (Data, Typeable)
import           GHC.Generics (Generic)

-- $types

-- | An opaque 'secretbox' cryptographic key.
newtype Key = Key ByteString deriving (Key -> Key -> Bool
(Key -> Key -> Bool) -> (Key -> Key -> Bool) -> Eq Key
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Key -> Key -> Bool
$c/= :: Key -> Key -> Bool
== :: Key -> Key -> Bool
$c== :: Key -> Key -> Bool
Eq, Eq Key
Eq Key =>
(Key -> Key -> Ordering)
-> (Key -> Key -> Bool)
-> (Key -> Key -> Bool)
-> (Key -> Key -> Bool)
-> (Key -> Key -> Bool)
-> (Key -> Key -> Key)
-> (Key -> Key -> Key)
-> Ord Key
Key -> Key -> Bool
Key -> Key -> Ordering
Key -> Key -> Key
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Key -> Key -> Key
$cmin :: Key -> Key -> Key
max :: Key -> Key -> Key
$cmax :: Key -> Key -> Key
>= :: Key -> Key -> Bool
$c>= :: Key -> Key -> Bool
> :: Key -> Key -> Bool
$c> :: Key -> Key -> Bool
<= :: Key -> Key -> Bool
$c<= :: Key -> Key -> Bool
< :: Key -> Key -> Bool
$c< :: Key -> Key -> Bool
compare :: Key -> Key -> Ordering
$ccompare :: Key -> Key -> Ordering
$cp1Ord :: Eq Key
Ord, Int -> Key -> Int
Key -> Int
(Int -> Key -> Int) -> (Key -> Int) -> Hashable Key
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Key -> Int
$chash :: Key -> Int
hashWithSalt :: Int -> Key -> Int
$chashWithSalt :: Int -> Key -> Int
Hashable, Typeable Key
DataType
Constr
Typeable Key =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> Key -> c Key)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Key)
-> (Key -> Constr)
-> (Key -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Key))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Key))
-> ((forall b. Data b => b -> b) -> Key -> Key)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Key -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Key -> r)
-> (forall u. (forall d. Data d => d -> u) -> Key -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Key -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Key -> m Key)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Key -> m Key)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Key -> m Key)
-> Data Key
Key -> DataType
Key -> Constr
(forall b. Data b => b -> b) -> Key -> Key
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Key -> c Key
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Key
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Key -> u
forall u. (forall d. Data d => d -> u) -> Key -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Key -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Key -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Key -> m Key
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Key -> m Key
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Key
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Key -> c Key
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Key)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Key)
$cKey :: Constr
$tKey :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Key -> m Key
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Key -> m Key
gmapMp :: (forall d. Data d => d -> m d) -> Key -> m Key
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Key -> m Key
gmapM :: (forall d. Data d => d -> m d) -> Key -> m Key
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Key -> m Key
gmapQi :: Int -> (forall d. Data d => d -> u) -> Key -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Key -> u
gmapQ :: (forall d. Data d => d -> u) -> Key -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Key -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Key -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Key -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Key -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Key -> r
gmapT :: (forall b. Data b => b -> b) -> Key -> Key
$cgmapT :: (forall b. Data b => b -> b) -> Key -> Key
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Key)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Key)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Key)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Key)
dataTypeOf :: Key -> DataType
$cdataTypeOf :: Key -> DataType
toConstr :: Key -> Constr
$ctoConstr :: Key -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Key
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Key
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Key -> c Key
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Key -> c Key
$cp1Data :: Typeable Key
Data, Typeable, (forall x. Key -> Rep Key x)
-> (forall x. Rep Key x -> Key) -> Generic Key
forall x. Rep Key x -> Key
forall x. Key -> Rep Key x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Key x -> Key
$cfrom :: forall x. Key -> Rep Key x
Generic)

instance IsEncoding Key where
  decode :: ByteString -> Maybe Key
decode v :: ByteString
v = if ByteString -> Int
S.length ByteString
v Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
Bytes.secretBoxKey
           then Key -> Maybe Key
forall a. a -> Maybe a
Just (ByteString -> Key
Key ByteString
v)
           else Maybe Key
forall a. Maybe a
Nothing
  {-# INLINE decode #-}
  encode :: Key -> ByteString
encode (Key v :: ByteString
v) = ByteString
v
  {-# INLINE encode #-}

-- | An opaque 'secretbox' nonce.
newtype Nonce = Nonce ByteString deriving (Nonce -> Nonce -> Bool
(Nonce -> Nonce -> Bool) -> (Nonce -> Nonce -> Bool) -> Eq Nonce
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Nonce -> Nonce -> Bool
$c/= :: Nonce -> Nonce -> Bool
== :: Nonce -> Nonce -> Bool
$c== :: Nonce -> Nonce -> Bool
Eq, Eq Nonce
Eq Nonce =>
(Nonce -> Nonce -> Ordering)
-> (Nonce -> Nonce -> Bool)
-> (Nonce -> Nonce -> Bool)
-> (Nonce -> Nonce -> Bool)
-> (Nonce -> Nonce -> Bool)
-> (Nonce -> Nonce -> Nonce)
-> (Nonce -> Nonce -> Nonce)
-> Ord Nonce
Nonce -> Nonce -> Bool
Nonce -> Nonce -> Ordering
Nonce -> Nonce -> Nonce
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Nonce -> Nonce -> Nonce
$cmin :: Nonce -> Nonce -> Nonce
max :: Nonce -> Nonce -> Nonce
$cmax :: Nonce -> Nonce -> Nonce
>= :: Nonce -> Nonce -> Bool
$c>= :: Nonce -> Nonce -> Bool
> :: Nonce -> Nonce -> Bool
$c> :: Nonce -> Nonce -> Bool
<= :: Nonce -> Nonce -> Bool
$c<= :: Nonce -> Nonce -> Bool
< :: Nonce -> Nonce -> Bool
$c< :: Nonce -> Nonce -> Bool
compare :: Nonce -> Nonce -> Ordering
$ccompare :: Nonce -> Nonce -> Ordering
$cp1Ord :: Eq Nonce
Ord, Int -> Nonce -> Int
Nonce -> Int
(Int -> Nonce -> Int) -> (Nonce -> Int) -> Hashable Nonce
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Nonce -> Int
$chash :: Nonce -> Int
hashWithSalt :: Int -> Nonce -> Int
$chashWithSalt :: Int -> Nonce -> Int
Hashable, Typeable Nonce
DataType
Constr
Typeable Nonce =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> Nonce -> c Nonce)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Nonce)
-> (Nonce -> Constr)
-> (Nonce -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Nonce))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Nonce))
-> ((forall b. Data b => b -> b) -> Nonce -> Nonce)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Nonce -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Nonce -> r)
-> (forall u. (forall d. Data d => d -> u) -> Nonce -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Nonce -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Nonce -> m Nonce)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Nonce -> m Nonce)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Nonce -> m Nonce)
-> Data Nonce
Nonce -> DataType
Nonce -> Constr
(forall b. Data b => b -> b) -> Nonce -> Nonce
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Nonce -> c Nonce
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Nonce
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Nonce -> u
forall u. (forall d. Data d => d -> u) -> Nonce -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Nonce -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Nonce -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Nonce -> m Nonce
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Nonce -> m Nonce
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Nonce
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Nonce -> c Nonce
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Nonce)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Nonce)
$cNonce :: Constr
$tNonce :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Nonce -> m Nonce
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Nonce -> m Nonce
gmapMp :: (forall d. Data d => d -> m d) -> Nonce -> m Nonce
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Nonce -> m Nonce
gmapM :: (forall d. Data d => d -> m d) -> Nonce -> m Nonce
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Nonce -> m Nonce
gmapQi :: Int -> (forall d. Data d => d -> u) -> Nonce -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Nonce -> u
gmapQ :: (forall d. Data d => d -> u) -> Nonce -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Nonce -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Nonce -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Nonce -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Nonce -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Nonce -> r
gmapT :: (forall b. Data b => b -> b) -> Nonce -> Nonce
$cgmapT :: (forall b. Data b => b -> b) -> Nonce -> Nonce
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Nonce)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Nonce)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Nonce)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Nonce)
dataTypeOf :: Nonce -> DataType
$cdataTypeOf :: Nonce -> DataType
toConstr :: Nonce -> Constr
$ctoConstr :: Nonce -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Nonce
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Nonce
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Nonce -> c Nonce
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Nonce -> c Nonce
$cp1Data :: Typeable Nonce
Data, Typeable, (forall x. Nonce -> Rep Nonce x)
-> (forall x. Rep Nonce x -> Nonce) -> Generic Nonce
forall x. Rep Nonce x -> Nonce
forall x. Nonce -> Rep Nonce x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Nonce x -> Nonce
$cfrom :: forall x. Nonce -> Rep Nonce x
Generic)

instance IsEncoding Nonce where
  decode :: ByteString -> Maybe Nonce
decode v :: ByteString
v = if ByteString -> Int
S.length ByteString
v Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
Bytes.secretBoxNonce
           then Nonce -> Maybe Nonce
forall a. a -> Maybe a
Just (ByteString -> Nonce
Nonce ByteString
v)
           else Maybe Nonce
forall a. Maybe a
Nothing
  {-# INLINE decode #-}
  encode :: Nonce -> ByteString
encode (Nonce v :: ByteString
v) = ByteString
v
  {-# INLINE encode #-}

instance IsNonce Nonce where
  zero :: Nonce
zero            = ByteString -> Nonce
Nonce (Int -> Word8 -> ByteString
S.replicate Int
Bytes.secretBoxNonce 0)
  nudge :: Nonce -> Nonce
nudge (Nonce n :: ByteString
n) = ByteString -> Nonce
Nonce (ByteString -> ByteString
nudgeBS ByteString
n)

-- | Creates a random key of the correct size for 'secretbox'.
newKey :: IO Key
newKey :: IO Key
newKey = ByteString -> Key
Key (ByteString -> Key) -> IO ByteString -> IO Key
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> IO ByteString
randomByteString Int
Bytes.secretBoxKey

-- | Creates a random nonce of the correct size for 'secretbox'.
newNonce :: IO Nonce
newNonce :: IO Nonce
newNonce = ByteString -> Nonce
Nonce (ByteString -> Nonce) -> IO ByteString -> IO Nonce
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> IO ByteString
randomByteString Int
Bytes.secretBoxNonce


-- | Encrypts a message. It is infeasible for an attacker to decrypt
-- the message so long as the 'Nonce' is never repeated.
aead :: Key -> Nonce
          -> ByteString
          -- ^ Message
          -> ByteString
          -- ^ AAD
          -> ByteString
          -- ^ Ciphertext
aead :: Key -> Nonce -> ByteString -> ByteString -> ByteString
aead (Key key :: ByteString
key) (Nonce nonce :: ByteString
nonce) msg :: ByteString
msg aad :: ByteString
aad =
  (CInt, ByteString) -> ByteString
forall a b. (a, b) -> b
snd ((CInt, ByteString) -> ByteString)
-> ((Ptr CChar -> IO CInt) -> (CInt, ByteString))
-> (Ptr CChar -> IO CInt)
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> (b, ByteString)
buildUnsafeByteString Int
clen ((Ptr CChar -> IO CInt) -> ByteString)
-> (Ptr CChar -> IO CInt) -> ByteString
forall a b. (a -> b) -> a -> b
$ \pc :: Ptr CChar
pc ->
    [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
key, ByteString
msg, ByteString
aad, ByteString
nonce] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \
      [(pk :: Ptr CChar
pk, _), (pm :: Ptr CChar
pm, _), (pa :: Ptr CChar
pa, _), (pn :: Ptr CChar
pn, _)] ->
          Ptr CChar
-> Ptr CULLong
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> Ptr CChar
-> Ptr CChar
-> IO CInt
c_aead Ptr CChar
pc Ptr CULLong
forall a. Ptr a
nullPtr Ptr CChar
pm (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
mlen) Ptr CChar
pa (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
alen) Ptr CChar
forall a. Ptr a
nullPtr Ptr CChar
pn Ptr CChar
pk
  where mlen :: Int
mlen    = ByteString -> Int
S.length ByteString
msg
        alen :: Int
alen    = ByteString -> Int
S.length ByteString
aad
        clen :: Int
clen    = Int
mlen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
Bytes.aead_xchacha20poly1305_ietf_ABYTES

-- | Decrypts a message. Returns 'Nothing' if the keys and message do
-- not match.
aeadOpen :: Key -> Nonce 
         -> ByteString
         -- ^ Ciphertext
         -> ByteString
         -- ^ AAD
         -> Maybe ByteString
         -- ^ Message
aeadOpen :: Key -> Nonce -> ByteString -> ByteString -> Maybe ByteString
aeadOpen (Key key :: ByteString
key) (Nonce nonce :: ByteString
nonce) cipher :: ByteString
cipher aad :: ByteString
aad = do
  let clen :: Int
clen   = ByteString -> Int
S.length ByteString
cipher
      alen :: Int
alen   = ByteString -> Int
S.length ByteString
aad
  Int
mlen <- Int
clen Int -> Int -> Maybe Int
forall a. (Ord a, Num a) => a -> a -> Maybe a
`safeSubtract` Int
Bytes.aead_xchacha20poly1305_ietf_ABYTES
  let (err :: CInt
err, vec :: ByteString
vec) = Int -> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> (b, ByteString)
buildUnsafeByteString Int
mlen ((Ptr CChar -> IO CInt) -> (CInt, ByteString))
-> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall a b. (a -> b) -> a -> b
$ \pm :: Ptr CChar
pm ->
        [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
key, ByteString
cipher, ByteString
aad, ByteString
nonce] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \
          [(pk :: Ptr CChar
pk, _), (pc :: Ptr CChar
pc, _), (pa :: Ptr CChar
pa, _), (pn :: Ptr CChar
pn, _)] ->
            Ptr CChar
-> Ptr CULLong
-> Ptr CChar
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> Ptr CChar
-> IO CInt
c_aead_open Ptr CChar
pm Ptr CULLong
forall a. Ptr a
nullPtr Ptr CChar
forall a. Ptr a
nullPtr Ptr CChar
pc (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
clen) Ptr CChar
pa (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
alen) Ptr CChar
pn Ptr CChar
pk
  Either String ByteString -> Maybe ByteString
forall s a. Either s a -> Maybe a
hush (Either String ByteString -> Maybe ByteString)
-> (ByteString -> Either String ByteString)
-> ByteString
-> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CInt -> ByteString -> Either String ByteString
forall a. CInt -> a -> Either String a
handleErrno CInt
err (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ ByteString
vec

-- | Encrypts a message. It is infeasible for an attacker to decrypt
-- the message so long as the 'Nonce' is never repeated.
aeadDetached :: Key -> Nonce
          -> ByteString
          -- ^ Message
          -> ByteString
          -- ^ AAD
          -> (ByteString,ByteString)
          -- ^ Tag, Ciphertext
aeadDetached :: Key
-> Nonce -> ByteString -> ByteString -> (ByteString, ByteString)
aeadDetached (Key key :: ByteString
key) (Nonce nonce :: ByteString
nonce) msg :: ByteString
msg aad :: ByteString
aad =
  Int -> (Ptr CChar -> IO ByteString) -> (ByteString, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> (b, ByteString)
buildUnsafeByteString Int
clen ((Ptr CChar -> IO ByteString) -> (ByteString, ByteString))
-> (Ptr CChar -> IO ByteString) -> (ByteString, ByteString)
forall a b. (a -> b) -> a -> b
$ \pc :: Ptr CChar
pc ->
   ((CInt, ByteString) -> ByteString)
-> IO (CInt, ByteString) -> IO ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CInt, ByteString) -> ByteString
forall a b. (a, b) -> b
snd (IO (CInt, ByteString) -> IO ByteString)
-> ((Ptr CChar -> IO CInt) -> IO (CInt, ByteString))
-> (Ptr CChar -> IO CInt)
-> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
buildUnsafeByteString' Int
tlen ((Ptr CChar -> IO CInt) -> IO ByteString)
-> (Ptr CChar -> IO CInt) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \pt :: Ptr CChar
pt ->
    [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
key, ByteString
msg, ByteString
aad, ByteString
nonce] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \
      [(pk :: Ptr CChar
pk, _), (pm :: Ptr CChar
pm, _), (pa :: Ptr CChar
pa, _), (pn :: Ptr CChar
pn, _)] ->
          Ptr CChar
-> Ptr CChar
-> Ptr CULLong
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> Ptr CChar
-> Ptr CChar
-> IO CInt
c_aead_detached Ptr CChar
pc Ptr CChar
pt Ptr CULLong
forall a. Ptr a
nullPtr Ptr CChar
pm (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
mlen) Ptr CChar
pa (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
alen) Ptr CChar
forall a. Ptr a
nullPtr Ptr CChar
pn Ptr CChar
pk
  where mlen :: Int
mlen    = ByteString -> Int
S.length ByteString
msg
        alen :: Int
alen    = ByteString -> Int
S.length ByteString
aad
        clen :: Int
clen    = Int
mlen
        tlen :: Int
tlen    = Int
Bytes.aead_xchacha20poly1305_ietf_ABYTES

-- | Decrypts a message. Returns 'Nothing' if the keys and message do
-- not match.
aeadOpenDetached :: Key -> Nonce
         -> ByteString
         -- ^ Tag
         -> ByteString
         -- ^ Ciphertext
         -> ByteString
         -- ^ AAD
         -> Maybe ByteString
         -- ^ Message
aeadOpenDetached :: Key
-> Nonce
-> ByteString
-> ByteString
-> ByteString
-> Maybe ByteString
aeadOpenDetached (Key key :: ByteString
key) (Nonce nonce :: ByteString
nonce) tag :: ByteString
tag cipher :: ByteString
cipher aad :: ByteString
aad
    | ByteString -> Int
S.length ByteString
tag Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
tlen = Maybe ByteString
forall a. Maybe a
Nothing
    | Bool
otherwise =
  let (err :: CInt
err, vec :: ByteString
vec) = Int -> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> (b, ByteString)
buildUnsafeByteString Int
len ((Ptr CChar -> IO CInt) -> (CInt, ByteString))
-> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall a b. (a -> b) -> a -> b
$ \pm :: Ptr CChar
pm ->
        [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
key, ByteString
tag, ByteString
cipher, ByteString
aad, ByteString
nonce] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \
          [(pk :: Ptr CChar
pk, _), (pt :: Ptr CChar
pt, _), (pc :: Ptr CChar
pc, _), (pa :: Ptr CChar
pa, _), (pn :: Ptr CChar
pn, _)] ->
            Ptr CChar
-> Ptr CChar
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> Ptr CChar
-> IO CInt
c_aead_open_detached Ptr CChar
pm Ptr CChar
forall a. Ptr a
nullPtr Ptr CChar
pc (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) Ptr CChar
pt Ptr CChar
pa (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
alen) Ptr CChar
pn Ptr CChar
pk
  in Either String ByteString -> Maybe ByteString
forall s a. Either s a -> Maybe a
hush (Either String ByteString -> Maybe ByteString)
-> (ByteString -> Either String ByteString)
-> ByteString
-> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CInt -> ByteString -> Either String ByteString
forall a. CInt -> a -> Either String a
handleErrno CInt
err (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ ByteString
vec
  where len :: Int
len    = ByteString -> Int
S.length ByteString
cipher
        alen :: Int
alen   = ByteString -> Int
S.length ByteString
aad
        tlen :: Int
tlen   = Int
Bytes.aead_xchacha20poly1305_ietf_ABYTES

-- | The aead C API uses C strings. Always returns 0.
foreign import ccall "crypto_aead_xchacha20poly1305_ietf_encrypt"
  c_aead :: Ptr CChar
              -- ^ Cipher output buffer
              -> Ptr CULLong
              -- ^ Cipher output bytes used
              -> Ptr CChar
              -- ^ Constant message input buffer
              -> CULLong
              -- ^ Length of message input buffer
              -> Ptr CChar
              -- ^ Constant aad input buffer
              -> CULLong
              -- ^ Length of aad input buffer
              -> Ptr CChar
              -- ^ Unused 'nsec' value (must be NULL)
              -> Ptr CChar
              -- ^ Constant nonce buffer
              -> Ptr CChar
              -- ^ Constant key buffer
              -> IO CInt

-- | The aead open C API uses C strings. Returns 0 if successful.
foreign import ccall "crypto_aead_xchacha20poly1305_ietf_decrypt"
  c_aead_open :: Ptr CChar
              -- ^ Message output buffer
              -> Ptr CULLong
              -- ^ Message output bytes used
              -> Ptr CChar
              -- ^ Unused 'nsec' value (must be NULL)
              -> Ptr CChar
              -- ^ Constant ciphertext input buffer
              -> CULLong
              -- ^ Length of ciphertext input buffer
              -> Ptr CChar
              -- ^ Constant aad input buffer
              -> CULLong
              -- ^ Length of aad input buffer
              -> Ptr CChar
              -- ^ Constant nonce buffer
              -> Ptr CChar
              -- ^ Constant key buffer
              -> IO CInt

-- | The aead C API uses C strings. Always returns 0.
foreign import ccall "crypto_aead_xchacha20poly1305_ietf_encrypt_detached"
  c_aead_detached :: Ptr CChar
              -- ^ Cipher output buffer
              -> Ptr CChar
              -- ^ Tag output buffer
              -> Ptr CULLong
              -- ^ Tag bytes used
              -> Ptr CChar
              -- ^ Constant message input buffer
              -> CULLong
              -- ^ Length of message input buffer
              -> Ptr CChar
              -- ^ Constant aad input buffer
              -> CULLong
              -- ^ Length of aad input buffer
              -> Ptr CChar
              -- ^ Unused 'nsec' value (must be NULL)
              -> Ptr CChar
              -- ^ Constant nonce buffer
              -> Ptr CChar
              -- ^ Constant key buffer
              -> IO CInt

-- | The aead open C API uses C strings. Returns 0 if successful.
foreign import ccall "crypto_aead_xchacha20poly1305_ietf_decrypt_detached"
  c_aead_open_detached :: Ptr CChar
              -- ^ Message output buffer
              -> Ptr CChar
              -- ^ Unused 'nsec' value (must be NULL)
              -> Ptr CChar
              -- ^ Constant ciphertext input buffer
              -> CULLong
              -- ^ Length of ciphertext input buffer
              -> Ptr CChar
              -- ^ Constant tag input buffer
              -> Ptr CChar
              -- ^ Constant aad input buffer
              -> CULLong
              -- ^ Length of aad input buffer
              -> Ptr CChar
              -- ^ Constant nonce buffer
              -> Ptr CChar
              -- ^ Constant key buffer
              -> IO CInt