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

module Botan.Low.PubKey.KeyEncapsulation
(

-- * PK Key Encapsulation
-- $introduction
-- * Usage
-- $usage

-- * KEM Encryption
  KEMSharedKey(..)
, KEMEncapsulatedKey(..)
, KEMEncrypt(..)
, withKEMEncrypt
, kemEncryptDestroy
, kemEncryptCreate
, kemEncryptSharedKeyLength
, kemEncryptEncapsulatedKeyLength
, kemEncryptCreateSharedKey

-- * KEM Decryption
, KEMDecrypt(..)
, withKEMDecrypt
, kemDecryptDestroy
, kemDecryptCreate
, kemDecryptSharedKeyLength
, kemDecryptSharedKey

) where

import qualified Data.ByteString as ByteString

import Botan.Bindings.PubKey.KeyEncapsulation

import Botan.Low.Error
import Botan.Low.KDF
import Botan.Low.Make
import Botan.Low.Prelude
import Botan.Low.PubKey
import Botan.Low.Remake
import Botan.Low.RNG

{- $introduction

Key encapsulation (KEM) is a variation on public key encryption which is
commonly used by post-quantum secure schemes. Instead of choosing a random
secret and encrypting it, as in typical public key encryption, a KEM encryption
takes no inputs and produces two values, the shared secret and the encapsulated
key. The decryption operation takes in the encapsulated key and returns the
shared secret.

-}

{- $usage

> NOTE: KEM only requires the public knowledge of one person's key pair, unlike
> Key Agreement.

First, Alice generates her private and public key pair:

> import Botan.Low.PubKey
> import Botan.Low.PubKey.KeyEncapsulation
> import Botan.Low.Hash
> import Botan.Low.KDF
> import Botan.Low.RNG
> rng <- rngInit UserRNG
> -- Alice generates her private and public keys
> alicePrivKey <- privKeyCreate RSA "2048" rng
> alicePubKey <- privKeyExportPubKey alicePrivKey

Then, Alice shares her public key somewhere where others can see. When Bob
wants to create a shared key with Alice, they choose a KDF algorithm, generate
a salt, and choose a shared key length.

> kdfAlg = hkdf SHA256
> salt <- rngGet rng 4
> sharedKeyLength = 256

Then, Bob generates the shared + encapsulated key, and sends the
encapsulated key to Alice:

> encryptCtx <- kemEncryptCreate alicePubKey kdfAlg
> (bobSharedKey, encapsulatedKey) <- kemEncryptCreateSharedKey encryptCtx rng salt sharedKeyLength
> -- sendToAlice encapsulatedKey

Upon receiving the encapsulated key, Alice can decrypt and extract the shared
key using her private key:

> decryptCtx <- kemDecryptCreate alicePrivKey kdfAlg
> aliceSharedKey <- kemDecryptSharedKey decryptCtx salt encapsulatedKey sharedKeyLength
> bobSharedKey == aliceSharedKey
> -- True

Then, this shared key may be used for any suitable purpose.

-}

-- TODO: KEM supports the following key types:
--      RSA
--      Kyber
--      McEliece
--  https://botan.randombit.net/handbook/api_ref/pubkey.html#key-encapsulation
-- KYBER is post-quantum

type KEMSharedKey = ByteString
type KEMEncapsulatedKey = ByteString

newtype KEMEncrypt = MkKEMEncrypt { KEMEncrypt -> ForeignPtr BotanPKOpKEMEncryptStruct
getKEMEncryptForeignPtr :: ForeignPtr BotanPKOpKEMEncryptStruct }

newKEMEncrypt      :: BotanPKOpKEMEncrypt -> IO KEMEncrypt
withKEMEncrypt     :: KEMEncrypt -> (BotanPKOpKEMEncrypt -> IO a) -> IO a
kemEncryptDestroy  :: KEMEncrypt -> IO ()
createKEMEncrypt   :: (Ptr BotanPKOpKEMEncrypt -> IO CInt) -> IO KEMEncrypt
(BotanPKOpKEMEncrypt -> IO KEMEncrypt
newKEMEncrypt, KEMEncrypt -> (BotanPKOpKEMEncrypt -> IO a) -> IO a
withKEMEncrypt, KEMEncrypt -> IO ()
kemEncryptDestroy, (Ptr BotanPKOpKEMEncrypt -> IO CInt) -> IO KEMEncrypt
createKEMEncrypt, (Ptr BotanPKOpKEMEncrypt -> Ptr CSize -> IO CInt)
-> IO [KEMEncrypt]
_)
    = (Ptr BotanPKOpKEMEncryptStruct -> BotanPKOpKEMEncrypt)
-> (BotanPKOpKEMEncrypt -> Ptr BotanPKOpKEMEncryptStruct)
-> (ForeignPtr BotanPKOpKEMEncryptStruct -> KEMEncrypt)
-> (KEMEncrypt -> ForeignPtr BotanPKOpKEMEncryptStruct)
-> FinalizerPtr BotanPKOpKEMEncryptStruct
-> (BotanPKOpKEMEncrypt -> IO KEMEncrypt,
    KEMEncrypt -> (BotanPKOpKEMEncrypt -> IO a) -> IO a,
    KEMEncrypt -> IO (),
    (Ptr BotanPKOpKEMEncrypt -> IO CInt) -> IO KEMEncrypt,
    (Ptr BotanPKOpKEMEncrypt -> Ptr CSize -> IO CInt)
    -> IO [KEMEncrypt])
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 BotanPKOpKEMEncryptStruct -> BotanPKOpKEMEncrypt
MkBotanPKOpKEMEncrypt BotanPKOpKEMEncrypt -> Ptr BotanPKOpKEMEncryptStruct
runBotanPKOpKEMEncrypt
        ForeignPtr BotanPKOpKEMEncryptStruct -> KEMEncrypt
MkKEMEncrypt KEMEncrypt -> ForeignPtr BotanPKOpKEMEncryptStruct
getKEMEncryptForeignPtr
        FinalizerPtr BotanPKOpKEMEncryptStruct
botan_pk_op_kem_encrypt_destroy





kemEncryptCreate
    :: PubKey           -- ^ __key__
    -> KDFName          -- ^ __kdf__
    -> IO KEMEncrypt    -- ^ __op__
kemEncryptCreate :: PubKey -> KEMSharedKey -> IO KEMEncrypt
kemEncryptCreate PubKey
pk KEMSharedKey
algo = PubKey -> (BotanPubKey -> IO KEMEncrypt) -> IO KEMEncrypt
forall a. PubKey -> (BotanPubKey -> IO a) -> IO a
withPubKey PubKey
pk ((BotanPubKey -> IO KEMEncrypt) -> IO KEMEncrypt)
-> (BotanPubKey -> IO KEMEncrypt) -> IO KEMEncrypt
forall a b. (a -> b) -> a -> b
$ \ BotanPubKey
pkPtr -> do
    KEMSharedKey -> (Ptr CChar -> IO KEMEncrypt) -> IO KEMEncrypt
forall a. KEMSharedKey -> (Ptr CChar -> IO a) -> IO a
asCString KEMSharedKey
algo ((Ptr CChar -> IO KEMEncrypt) -> IO KEMEncrypt)
-> (Ptr CChar -> IO KEMEncrypt) -> IO KEMEncrypt
forall a b. (a -> b) -> a -> b
$ \ Ptr CChar
algoPtr -> do
        (Ptr BotanPKOpKEMEncrypt -> IO CInt) -> IO KEMEncrypt
createKEMEncrypt ((Ptr BotanPKOpKEMEncrypt -> IO CInt) -> IO KEMEncrypt)
-> (Ptr BotanPKOpKEMEncrypt -> IO CInt) -> IO KEMEncrypt
forall a b. (a -> b) -> a -> b
$ \ Ptr BotanPKOpKEMEncrypt
out -> Ptr BotanPKOpKEMEncrypt -> BotanPubKey -> ConstPtr CChar -> IO CInt
botan_pk_op_kem_encrypt_create
            Ptr BotanPKOpKEMEncrypt
out
            BotanPubKey
pkPtr
            (Ptr CChar -> ConstPtr CChar
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr CChar
algoPtr)

-- WARNING: withFooInit-style limited lifetime functions moved to high-level botan
withKEMEncryptCreate :: PubKey -> KDFName -> (KEMEncrypt -> IO a) -> IO a
withKEMEncryptCreate :: forall a. PubKey -> KEMSharedKey -> (KEMEncrypt -> IO a) -> IO a
withKEMEncryptCreate = (PubKey -> KEMSharedKey -> IO KEMEncrypt)
-> (KEMEncrypt -> IO ())
-> PubKey
-> KEMSharedKey
-> (KEMEncrypt -> IO a)
-> IO a
forall x y t a.
(x -> y -> IO t) -> (t -> IO ()) -> x -> y -> (t -> IO a) -> IO a
mkWithTemp2 PubKey -> KEMSharedKey -> IO KEMEncrypt
kemEncryptCreate KEMEncrypt -> IO ()
kemEncryptDestroy

kemEncryptSharedKeyLength
    :: KEMEncrypt   -- ^ __op__
    -> Int          -- ^ __desired_shared_key_length__
    -> IO Int       -- ^ __output_shared_key_length__
kemEncryptSharedKeyLength :: KEMEncrypt -> Int -> IO Int
kemEncryptSharedKeyLength = WithPtr KEMEncrypt BotanPKOpKEMEncrypt
-> GetSize_csize BotanPKOpKEMEncrypt -> KEMEncrypt -> Int -> IO Int
forall typ ptr.
WithPtr typ ptr -> GetSize_csize ptr -> typ -> Int -> IO Int
mkGetSize_csize KEMEncrypt -> (BotanPKOpKEMEncrypt -> IO a) -> IO a
WithPtr KEMEncrypt BotanPKOpKEMEncrypt
withKEMEncrypt GetSize_csize BotanPKOpKEMEncrypt
botan_pk_op_kem_encrypt_shared_key_length


kemEncryptEncapsulatedKeyLength
    :: KEMEncrypt   -- ^ __op__
    -> IO Int       -- ^ __output_encapsulated_key_length__
kemEncryptEncapsulatedKeyLength :: KEMEncrypt -> IO Int
kemEncryptEncapsulatedKeyLength = WithPtr KEMEncrypt BotanPKOpKEMEncrypt
-> GetSize BotanPKOpKEMEncrypt -> KEMEncrypt -> IO Int
forall typ ptr. WithPtr typ ptr -> GetSize ptr -> typ -> IO Int
mkGetSize KEMEncrypt -> (BotanPKOpKEMEncrypt -> IO a) -> IO a
WithPtr KEMEncrypt BotanPKOpKEMEncrypt
withKEMEncrypt GetSize BotanPKOpKEMEncrypt
botan_pk_op_kem_encrypt_encapsulated_key_length

-- NOTE: Awkward because of double-query and returning double bytestrings
--  Cannot use allocBytesQuerying because of double-return
-- NOTE: Returns (SharedKey, EncapsulatedKey)


kemEncryptCreateSharedKey
    :: KEMEncrypt                           -- ^ __op__
    -> RNG                                  -- ^ __rng__
    -> ByteString                           -- ^ __salt[]__
    -> Int                                  -- ^ __desired_shared_key_len__
    -> IO (KEMSharedKey,KEMEncapsulatedKey) -- ^ __(shared_key,encapsulated_key)__
kemEncryptCreateSharedKey :: KEMEncrypt
-> RNG -> KEMSharedKey -> Int -> IO (KEMSharedKey, KEMSharedKey)
kemEncryptCreateSharedKey KEMEncrypt
ke RNG
rng KEMSharedKey
salt Int
desiredLen = KEMEncrypt
-> (BotanPKOpKEMEncrypt -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
WithPtr KEMEncrypt BotanPKOpKEMEncrypt
withKEMEncrypt KEMEncrypt
ke ((BotanPKOpKEMEncrypt -> IO (KEMSharedKey, KEMSharedKey))
 -> IO (KEMSharedKey, KEMSharedKey))
-> (BotanPKOpKEMEncrypt -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall a b. (a -> b) -> a -> b
$ \ BotanPKOpKEMEncrypt
kePtr -> do
    RNG
-> (BotanRNG -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall a. RNG -> (BotanRNG -> IO a) -> IO a
withRNG RNG
rng ((BotanRNG -> IO (KEMSharedKey, KEMSharedKey))
 -> IO (KEMSharedKey, KEMSharedKey))
-> (BotanRNG -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall a b. (a -> b) -> a -> b
$ \ BotanRNG
botanRNG -> do
        KEMSharedKey
-> (Ptr Word8 -> CSize -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall byte a. KEMSharedKey -> (Ptr byte -> CSize -> IO a) -> IO a
asBytesLen KEMSharedKey
salt ((Ptr Word8 -> CSize -> IO (KEMSharedKey, KEMSharedKey))
 -> IO (KEMSharedKey, KEMSharedKey))
-> (Ptr Word8 -> CSize -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
saltPtr CSize
saltLen -> do
            (Ptr CSize -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CSize -> IO (KEMSharedKey, KEMSharedKey))
 -> IO (KEMSharedKey, KEMSharedKey))
-> (Ptr CSize -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall a b. (a -> b) -> a -> b
$ \ Ptr CSize
sharedSzPtr -> do 
                (Ptr CSize -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CSize -> IO (KEMSharedKey, KEMSharedKey))
 -> IO (KEMSharedKey, KEMSharedKey))
-> (Ptr CSize -> IO (KEMSharedKey, KEMSharedKey))
-> IO (KEMSharedKey, KEMSharedKey)
forall a b. (a -> b) -> a -> b
$ \ Ptr CSize
encapSzPtr -> do
                    Int
sharedSz <- KEMEncrypt -> Int -> IO Int
kemEncryptSharedKeyLength KEMEncrypt
ke Int
desiredLen
                    Int
encapSz <-  KEMEncrypt -> IO Int
kemEncryptEncapsulatedKeyLength KEMEncrypt
ke
                    Ptr CSize -> CSize -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr CSize
sharedSzPtr (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sharedSz)
                    Ptr CSize -> CSize -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr CSize
encapSzPtr (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
encapSz)
                    Int
-> (Ptr Word8 -> IO KEMSharedKey)
-> IO (KEMSharedKey, KEMSharedKey)
forall byte a. Int -> (Ptr byte -> IO a) -> IO (a, KEMSharedKey)
allocBytesWith Int
encapSz ((Ptr Word8 -> IO KEMSharedKey) -> IO (KEMSharedKey, KEMSharedKey))
-> (Ptr Word8 -> IO KEMSharedKey)
-> IO (KEMSharedKey, KEMSharedKey)
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
encapPtr -> do
                        Int -> (Ptr Word8 -> IO ()) -> IO KEMSharedKey
forall byte. Int -> (Ptr byte -> IO ()) -> IO KEMSharedKey
allocBytes Int
sharedSz ((Ptr Word8 -> IO ()) -> IO KEMSharedKey)
-> (Ptr Word8 -> IO ()) -> IO KEMSharedKey
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
sharedPtr -> do
                            HasCallStack => IO CInt -> IO ()
IO CInt -> IO ()
throwBotanIfNegative_ (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanPKOpKEMEncrypt
-> BotanRNG
-> ConstPtr Word8
-> CSize
-> CSize
-> Ptr Word8
-> Ptr CSize
-> Ptr Word8
-> Ptr CSize
-> IO CInt
botan_pk_op_kem_encrypt_create_shared_key
                                BotanPKOpKEMEncrypt
kePtr
                                BotanRNG
botanRNG
                                (Ptr Word8 -> ConstPtr Word8
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr Word8
saltPtr)
                                CSize
saltLen
                                (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
desiredLen)
                                Ptr Word8
sharedPtr
                                Ptr CSize
sharedSzPtr
                                Ptr Word8
encapPtr
                                Ptr CSize
encapSzPtr

newtype KEMDecrypt = MkKEMDecrypt { KEMDecrypt -> ForeignPtr BotanPKOpKEMDecryptStruct
getKEMDecryptForeignPtr :: ForeignPtr BotanPKOpKEMDecryptStruct }

newKEMDecrypt      :: BotanPKOpKEMDecrypt -> IO KEMDecrypt
withKEMDecrypt     :: KEMDecrypt -> (BotanPKOpKEMDecrypt -> IO a) -> IO a
kemDecryptDestroy  :: KEMDecrypt -> IO ()
createKEMDecrypt   :: (Ptr BotanPKOpKEMDecrypt -> IO CInt) -> IO KEMDecrypt
(BotanPKOpKEMDecrypt -> IO KEMDecrypt
newKEMDecrypt, KEMDecrypt -> (BotanPKOpKEMDecrypt -> IO a) -> IO a
withKEMDecrypt, KEMDecrypt -> IO ()
kemDecryptDestroy, (Ptr BotanPKOpKEMDecrypt -> IO CInt) -> IO KEMDecrypt
createKEMDecrypt, (Ptr BotanPKOpKEMDecrypt -> Ptr CSize -> IO CInt)
-> IO [KEMDecrypt]
_)
    = (Ptr BotanPKOpKEMDecryptStruct -> BotanPKOpKEMDecrypt)
-> (BotanPKOpKEMDecrypt -> Ptr BotanPKOpKEMDecryptStruct)
-> (ForeignPtr BotanPKOpKEMDecryptStruct -> KEMDecrypt)
-> (KEMDecrypt -> ForeignPtr BotanPKOpKEMDecryptStruct)
-> FinalizerPtr BotanPKOpKEMDecryptStruct
-> (BotanPKOpKEMDecrypt -> IO KEMDecrypt,
    KEMDecrypt -> (BotanPKOpKEMDecrypt -> IO a) -> IO a,
    KEMDecrypt -> IO (),
    (Ptr BotanPKOpKEMDecrypt -> IO CInt) -> IO KEMDecrypt,
    (Ptr BotanPKOpKEMDecrypt -> Ptr CSize -> IO CInt)
    -> IO [KEMDecrypt])
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 BotanPKOpKEMDecryptStruct -> BotanPKOpKEMDecrypt
MkBotanPKOpKEMDecrypt BotanPKOpKEMDecrypt -> Ptr BotanPKOpKEMDecryptStruct
runBotanPKOpKEMDecrypt
        ForeignPtr BotanPKOpKEMDecryptStruct -> KEMDecrypt
MkKEMDecrypt KEMDecrypt -> ForeignPtr BotanPKOpKEMDecryptStruct
getKEMDecryptForeignPtr
        FinalizerPtr BotanPKOpKEMDecryptStruct
botan_pk_op_kem_decrypt_destroy

kemDecryptCreate
    :: PrivKey          -- ^ __key__
    -> KDFName          -- ^ __kdf__
    -> IO KEMDecrypt    -- ^ __op__
kemDecryptCreate :: PrivKey -> KEMSharedKey -> IO KEMDecrypt
kemDecryptCreate PrivKey
sk KEMSharedKey
algo = PrivKey -> (BotanPrivKey -> IO KEMDecrypt) -> IO KEMDecrypt
forall a. PrivKey -> (BotanPrivKey -> IO a) -> IO a
withPrivKey PrivKey
sk ((BotanPrivKey -> IO KEMDecrypt) -> IO KEMDecrypt)
-> (BotanPrivKey -> IO KEMDecrypt) -> IO KEMDecrypt
forall a b. (a -> b) -> a -> b
$ \ BotanPrivKey
skPtr -> do
    KEMSharedKey -> (Ptr CChar -> IO KEMDecrypt) -> IO KEMDecrypt
forall a. KEMSharedKey -> (Ptr CChar -> IO a) -> IO a
asCString KEMSharedKey
algo ((Ptr CChar -> IO KEMDecrypt) -> IO KEMDecrypt)
-> (Ptr CChar -> IO KEMDecrypt) -> IO KEMDecrypt
forall a b. (a -> b) -> a -> b
$ \ Ptr CChar
algoPtr -> do
        (Ptr BotanPKOpKEMDecrypt -> IO CInt) -> IO KEMDecrypt
createKEMDecrypt ((Ptr BotanPKOpKEMDecrypt -> IO CInt) -> IO KEMDecrypt)
-> (Ptr BotanPKOpKEMDecrypt -> IO CInt) -> IO KEMDecrypt
forall a b. (a -> b) -> a -> b
$ \ Ptr BotanPKOpKEMDecrypt
out -> Ptr BotanPKOpKEMDecrypt
-> BotanPrivKey -> ConstPtr CChar -> IO CInt
botan_pk_op_kem_decrypt_create
            Ptr BotanPKOpKEMDecrypt
out
            BotanPrivKey
skPtr
            (Ptr CChar -> ConstPtr CChar
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr CChar
algoPtr)

-- WARNING: withFooInit-style limited lifetime functions moved to high-level botan
withKEMDecryptCreate :: PrivKey -> KDFName -> (KEMDecrypt -> IO a) -> IO a
withKEMDecryptCreate :: forall a. PrivKey -> KEMSharedKey -> (KEMDecrypt -> IO a) -> IO a
withKEMDecryptCreate = (PrivKey -> KEMSharedKey -> IO KEMDecrypt)
-> (KEMDecrypt -> IO ())
-> PrivKey
-> KEMSharedKey
-> (KEMDecrypt -> IO a)
-> IO a
forall x y t a.
(x -> y -> IO t) -> (t -> IO ()) -> x -> y -> (t -> IO a) -> IO a
mkWithTemp2 PrivKey -> KEMSharedKey -> IO KEMDecrypt
kemDecryptCreate KEMDecrypt -> IO ()
kemDecryptDestroy

kemDecryptSharedKeyLength
    :: KEMDecrypt   -- ^ __op__
    -> Int          -- ^ __desired_shared_key_length__
    -> IO Int       -- ^ __output_shared_key_length__
kemDecryptSharedKeyLength :: KEMDecrypt -> Int -> IO Int
kemDecryptSharedKeyLength = WithPtr KEMDecrypt BotanPKOpKEMDecrypt
-> GetSize_csize BotanPKOpKEMDecrypt -> KEMDecrypt -> Int -> IO Int
forall typ ptr.
WithPtr typ ptr -> GetSize_csize ptr -> typ -> Int -> IO Int
mkGetSize_csize KEMDecrypt -> (BotanPKOpKEMDecrypt -> IO a) -> IO a
WithPtr KEMDecrypt BotanPKOpKEMDecrypt
withKEMDecrypt GetSize_csize BotanPKOpKEMDecrypt
botan_pk_op_kem_decrypt_shared_key_length

kemDecryptSharedKey
    :: KEMDecrypt           -- ^ __op__
    -> ByteString           -- ^ __salt[]__
    -> KEMEncapsulatedKey   -- ^ __encapsulated_key[]__
    -> Int                  -- ^ __desired_shared_key_len__
    -> IO KEMSharedKey      -- ^ __shared_key[]__
kemDecryptSharedKey :: KEMDecrypt
-> KEMSharedKey -> KEMSharedKey -> Int -> IO KEMSharedKey
kemDecryptSharedKey KEMDecrypt
kd KEMSharedKey
salt KEMSharedKey
encap Int
desiredLen = KEMDecrypt
-> (BotanPKOpKEMDecrypt -> IO KEMSharedKey) -> IO KEMSharedKey
WithPtr KEMDecrypt BotanPKOpKEMDecrypt
withKEMDecrypt KEMDecrypt
kd ((BotanPKOpKEMDecrypt -> IO KEMSharedKey) -> IO KEMSharedKey)
-> (BotanPKOpKEMDecrypt -> IO KEMSharedKey) -> IO KEMSharedKey
forall a b. (a -> b) -> a -> b
$ \ BotanPKOpKEMDecrypt
kdPtr -> do
    KEMSharedKey
-> (Ptr Word8 -> CSize -> IO KEMSharedKey) -> IO KEMSharedKey
forall byte a. KEMSharedKey -> (Ptr byte -> CSize -> IO a) -> IO a
asBytesLen KEMSharedKey
salt ((Ptr Word8 -> CSize -> IO KEMSharedKey) -> IO KEMSharedKey)
-> (Ptr Word8 -> CSize -> IO KEMSharedKey) -> IO KEMSharedKey
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
saltPtr CSize
saltLen -> do
        KEMSharedKey
-> (Ptr Word8 -> CSize -> IO KEMSharedKey) -> IO KEMSharedKey
forall byte a. KEMSharedKey -> (Ptr byte -> CSize -> IO a) -> IO a
asBytesLen KEMSharedKey
encap ((Ptr Word8 -> CSize -> IO KEMSharedKey) -> IO KEMSharedKey)
-> (Ptr Word8 -> CSize -> IO KEMSharedKey) -> IO KEMSharedKey
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
encapPtr CSize
encapLen -> do
            -- TODO: Consolidate with allocBytesUpperBound or whatever I end up calling it
            (Ptr CSize -> IO KEMSharedKey) -> IO KEMSharedKey
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CSize -> IO KEMSharedKey) -> IO KEMSharedKey)
-> (Ptr CSize -> IO KEMSharedKey) -> IO KEMSharedKey
forall a b. (a -> b) -> a -> b
$ \ Ptr CSize
sharedSzPtr -> do
                Int
sharedSz <- KEMDecrypt -> Int -> IO Int
kemDecryptSharedKeyLength KEMDecrypt
kd Int
desiredLen
                Ptr CSize -> CSize -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr CSize
sharedSzPtr (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sharedSz)
                KEMSharedKey
bytes <- Int -> (Ptr Word8 -> IO ()) -> IO KEMSharedKey
forall byte. Int -> (Ptr byte -> IO ()) -> IO KEMSharedKey
allocBytes Int
sharedSz ((Ptr Word8 -> IO ()) -> IO KEMSharedKey)
-> (Ptr Word8 -> IO ()) -> IO KEMSharedKey
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
outPtr -> do
                    HasCallStack => IO CInt -> IO ()
IO CInt -> IO ()
throwBotanIfNegative_ (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanPKOpKEMDecrypt
-> ConstPtr Word8
-> CSize
-> ConstPtr Word8
-> CSize
-> CSize
-> Ptr Word8
-> Ptr CSize
-> IO CInt
botan_pk_op_kem_decrypt_shared_key
                        BotanPKOpKEMDecrypt
kdPtr
                        (Ptr Word8 -> ConstPtr Word8
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr Word8
saltPtr)
                        CSize
saltLen
                        (Ptr Word8 -> ConstPtr Word8
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr Word8
encapPtr)
                        CSize
encapLen
                        (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
desiredLen)
                        Ptr Word8
outPtr
                        Ptr CSize
sharedSzPtr
                CSize
actualSharedSz <- Ptr CSize -> IO CSize
forall a. Storable a => Ptr a -> IO a
peek Ptr CSize
sharedSzPtr
                KEMSharedKey -> IO KEMSharedKey
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (KEMSharedKey -> IO KEMSharedKey)
-> KEMSharedKey -> IO KEMSharedKey
forall a b. NFData a => (a -> b) -> a -> b
$!! Int -> KEMSharedKey -> KEMSharedKey
ByteString.take (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
actualSharedSz) KEMSharedKey
bytes