{-|
Module      : Z.Crypto.PubKey
Description : Public Key Cryptography
Copyright   : Dong Han, 2021
              AnJie Dong, 2021
License     : BSD
Maintainer  : winterland1989@gmail.com
Stability   : experimental
Portability : non-portable

This module is used for Public key cryptography. Public key cryptography (also called asymmetric cryptography) is a collection of techniques allowing for encryption, signatures, and key agreement.
-}

module Z.Crypto.PubKey (
  -- * Asymmetric cryptography algorithms
    KeyType(..)
  -- * Key generation and manipulation
  , PrivKey, PubKey
  , newPrivKey, newKeyPair, privKeyToPubKey
  , loadPrivKey
  , privKeyAlgoName
  , privKeyParam
  , exportPrivKeyDER, exportPrivKeyPEM
  , exportPrivKeyEncryptedDER, exportPrivKeyEncryptedPEM
  , loadPubKey
  , pubKeyAlgoName
  , pubKeyParam
  , exportPubKeyDER
  , exportPubKeyPEM
  , estStrength
  , fingerPrintPubKey
  -- * Encrypt & Decrypt
  , pkEncrypt
  , pkDecrypt
  , EncParam(..)
  -- * Sign & verify
  , SignParam(..), SignFmt(..), Signer, signerSize, Verifier
  , newSigner, updateSigner, finalSigner, sinkToSigner, sign, signChunks
  , newVerifier, updateVerifier, finalVerifier, sinkToVerifier, verify, verifyChunks
  -- * Key agreement
  , KeyAgreement, keyAgreementSize
  , newKeyAgreement
  , exportKeyAgreementPublic
  , keyAgree
  -- * RSA specific
  , getRSAParams
  , newRSAPrivKey
  , getRSAPubParams
  , newRSAPubKey
  -- * DSA specific
  , getDSAPrivParams
  , newDSAPrivKey
  , getDSAPubParams
  , newDSAPubKey
  -- * ElGamal specific
  , getElGamalPrivParams
  , newElGamalPrivKey
  , getElGamalPubParams
  , newElGamalPubKey
  -- * Diffie-Hellman specific
  , getDHPrivParams
  , newDHPrivKey
  , getDHPubParams
  , newDHPubKey
  -- * constants
  , XMSSType
  , pattern XMSS_SHA2_10_256
  , pattern XMSS_SHA2_16_256
  , pattern XMSS_SHA2_20_256
  , pattern XMSS_SHA2_10_512
  , pattern XMSS_SHA2_16_512
  , pattern XMSS_SHA2_20_512
  , pattern XMSS_SHAKE_10_256
  , pattern XMSS_SHAKE_16_256
  , pattern XMSS_SHAKE_20_256
  , pattern XMSS_SHAKE_10_512
  , pattern XMSS_SHAKE_16_512
  , pattern XMSS_SHAKE_20_512
  , ECGroup
  , pattern Secp160k1
  , pattern Secp160r1
  , pattern Secp160r2
  , pattern Secp192k1
  , pattern Secp192r1
  , pattern Secp224k1
  , pattern Secp224r1
  , pattern Secp256k1
  , pattern Secp256r1
  , pattern Secp384r1
  , pattern Secp521r1
  , pattern Brainpool160r1
  , pattern Brainpool192r1
  , pattern Brainpool224r1
  , pattern Brainpool256r1
  , pattern Brainpool320r1
  , pattern Brainpool384r1
  , pattern Brainpool512r1
  , pattern X962_p192v2
  , pattern X962_p192v3
  , pattern X962_p239v1
  , pattern X962_p239v2
  , pattern X962_p239v3
  , pattern Gost_256A
  , pattern Gost_512A
  , pattern Frp256v1
  , pattern Sm2p256v1
  , DLGroup
  , pattern FFDHE_IETF_2048
  , pattern FFDHE_IETF_3072
  , pattern FFDHE_IETF_4096
  , pattern FFDHE_IETF_6144
  , pattern FFDHE_IETF_8192
  , pattern MODP_IETF_1024
  , pattern MODP_IETF_1536
  , pattern MODP_IETF_2048
  , pattern MODP_IETF_3072
  , pattern MODP_IETF_4096
  , pattern MODP_IETF_6144
  , pattern MODP_IETF_8192
  , pattern MODP_SRP_1024
  , pattern MODP_SRP_1536
  , pattern MODP_SRP_2048
  , pattern MODP_SRP_3072
  , pattern MODP_SRP_4096
  , pattern MODP_SRP_6144
  , pattern MODP_SRP_8192
  , pattern DSA_JCE_1024
  , pattern DSA_BOTAN_2048
  , pattern DSA_BOTAN_3072
  -- * re-exports
  , HashType(..)
  , KDFType(..)
  , RNG, getRNG
  -- * internal
  , withPrivKey
  , withPubKey
  , botanStructToPubKey
  ) where

import           Data.Word
import           GHC.Generics
import           System.IO.Unsafe    (unsafePerformIO)
import           Z.Botan.Exception
import           Z.Botan.FFI
import           Z.Crypto.Hash       (HashType(..), hashTypeToCBytes)
import           Z.Crypto.KDF        (KDFType(..), kdfTypeToCBytes)
import           Z.Crypto.MPI
import           Z.Crypto.RNG        (RNG, getRNG, withRNG)
import           Z.Crypto.SafeMem
import qualified Z.Data.Builder      as B
import           Z.Data.CBytes       (CBytes)
import qualified Z.Data.CBytes       as CB
import           Z.Data.JSON         (JSON)
import qualified Z.Data.Text         as T
import qualified Z.Data.Vector       as V
import           Z.Foreign
import           Z.IO.BIO

---------------
-- Key Types --
---------------

-- | Public key cryptography algorithms.
data KeyType
    = RSA Word32        -- ^ RSA key of the given size, namely n bits, support encryption and signature.
    | SM2 ECGroup       -- ^ Public key algorithms specified by China, support encryption and signature.
    | ElGamal DLGroup   -- ^ ElGamal encryption system, support encryption.

    | DSA DLGroup     -- ^ Digital Signature Algorithm based on the discrete logarithm problem.
    | ECDSA ECGroup   -- ^ Digital Signature Algorithm which uses elliptic curve cryptography.
    | ECKCDSA ECGroup -- ^ Korean Certificate-based Digital Signature Algorithm.
    | ECGDSA ECGroup  -- ^ Elliptic Curve German Digital Signature Algorithm.
    | GOST_34'10 ECGroup -- ^ Cryptographic algorithms defined by the Russian national standards, support signature.
    | Ed25519         -- ^ Ed25519 elliptic-curve signatures, see <https://ed25519.cr.yp.to/ ed25519>.
    | XMSS XMSSType   -- ^ eXtended Merkle Signature Scheme, see <xmss https://botan.randombit.net/handbook/api_ref/pubkey.html#extended-merkle-signature-scheme-xmss>.

    | DH DLGroup        -- ^ The Diffie–Hellman key exchange.
    | ECDH ECGroup      -- ^ The Elliptic-curve Diffie–Hellman key exchange.
    | Curve25519        -- ^ The Curve25519 Diffie–Hellman key exchange.

keyTypeToCBytes :: KeyType -> (CBytes, CBytes)
keyTypeToCBytes :: KeyType -> (CBytes, CBytes)
keyTypeToCBytes KeyType
keyType = case KeyType
keyType of
    RSA Word32
bits    -> (CBytes
"RSA", Builder () -> CBytes
forall a. Builder a -> CBytes
CB.buildCBytes (Builder () -> CBytes) -> Builder () -> CBytes
forall a b. (a -> b) -> a -> b
$ Word32 -> Builder ()
forall a. (Integral a, Bounded a) => a -> Builder ()
B.int Word32
bits)
    SM2 CBytes
grp     -> (CBytes
"SM2", CBytes
grp)
    ElGamal CBytes
grp -> (CBytes
"ElGamal", CBytes
grp)
    DSA CBytes
grp         -> (CBytes
"DSA", CBytes
grp)
    ECDSA CBytes
grp       -> (CBytes
"ECDSA", CBytes
grp)
    ECKCDSA CBytes
grp     -> (CBytes
"ECKCDSA", CBytes
grp)
    ECGDSA CBytes
grp      -> (CBytes
"ECGDSA", CBytes
grp)
    GOST_34'10 CBytes
grp  -> (CBytes
"GOST_34.10", CBytes
grp)
    KeyType
Ed25519         -> (CBytes
"Ed25519", CBytes
"")
    XMSS CBytes
xms        -> (CBytes
"XMSS", CBytes
xms)
    DH CBytes
grp      -> (CBytes
"DH", CBytes
grp)
    ECDH CBytes
grp    -> (CBytes
"ECDH", CBytes
grp)
    KeyType
Curve25519  -> (CBytes
"Curve25519", CBytes
"")

-- | A type wrapper.
type XMSSType = CBytes

pattern XMSS_SHA2_10_256 :: XMSSType
pattern $bXMSS_SHA2_10_256 :: CBytes
$mXMSS_SHA2_10_256 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHA2_10_256 = "XMSS-SHA2_10_256"

pattern XMSS_SHA2_16_256 :: XMSSType
pattern $bXMSS_SHA2_16_256 :: CBytes
$mXMSS_SHA2_16_256 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHA2_16_256 = "XMSS-SHA2_16_256"

pattern XMSS_SHA2_20_256 :: XMSSType
pattern $bXMSS_SHA2_20_256 :: CBytes
$mXMSS_SHA2_20_256 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHA2_20_256 = "XMSS-SHA2_20_256"

pattern XMSS_SHA2_10_512 :: XMSSType
pattern $bXMSS_SHA2_10_512 :: CBytes
$mXMSS_SHA2_10_512 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHA2_10_512 = "XMSS-SHA2_10_512"

pattern XMSS_SHA2_16_512 :: XMSSType
pattern $bXMSS_SHA2_16_512 :: CBytes
$mXMSS_SHA2_16_512 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHA2_16_512 = "XMSS-SHA2_16_512"

pattern XMSS_SHA2_20_512 :: XMSSType
pattern $bXMSS_SHA2_20_512 :: CBytes
$mXMSS_SHA2_20_512 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHA2_20_512 = "XMSS-SHA2_20_512"

pattern XMSS_SHAKE_10_256 :: XMSSType
pattern $bXMSS_SHAKE_10_256 :: CBytes
$mXMSS_SHAKE_10_256 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHAKE_10_256 = "XMSS-SHAKE_10_256"

pattern XMSS_SHAKE_16_256 :: XMSSType
pattern $bXMSS_SHAKE_16_256 :: CBytes
$mXMSS_SHAKE_16_256 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHAKE_16_256 = "XMSS-SHAKE_16_256"

pattern XMSS_SHAKE_20_256 :: XMSSType
pattern $bXMSS_SHAKE_20_256 :: CBytes
$mXMSS_SHAKE_20_256 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHAKE_20_256 = "XMSS-SHAKE_20_256"

pattern XMSS_SHAKE_10_512 :: XMSSType
pattern $bXMSS_SHAKE_10_512 :: CBytes
$mXMSS_SHAKE_10_512 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHAKE_10_512 = "XMSS-SHAKE_10_512"

pattern XMSS_SHAKE_16_512 :: XMSSType
pattern $bXMSS_SHAKE_16_512 :: CBytes
$mXMSS_SHAKE_16_512 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHAKE_16_512 = "XMSS-SHAKE_16_512"

pattern XMSS_SHAKE_20_512 :: XMSSType
pattern $bXMSS_SHAKE_20_512 :: CBytes
$mXMSS_SHAKE_20_512 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
XMSS_SHAKE_20_512 = "XMSS-SHAKE_20_512"

-- | An elliptic curve.
type ECGroup = CBytes

pattern Secp160k1 :: ECGroup
pattern $bSecp160k1 :: CBytes
$mSecp160k1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp160k1 = "secp160k1"

pattern Secp160r1 :: ECGroup
pattern $bSecp160r1 :: CBytes
$mSecp160r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp160r1 = "secp160r1"

pattern Secp160r2 :: ECGroup
pattern $bSecp160r2 :: CBytes
$mSecp160r2 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp160r2 = "secp160r2"

pattern Secp192k1 :: ECGroup
pattern $bSecp192k1 :: CBytes
$mSecp192k1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp192k1 = "secp192k1"

pattern Secp192r1 :: ECGroup
pattern $bSecp192r1 :: CBytes
$mSecp192r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp192r1 = "secp192r1"

pattern Secp224k1 :: ECGroup
pattern $bSecp224k1 :: CBytes
$mSecp224k1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp224k1 = "secp224k1"

pattern Secp224r1 :: ECGroup
pattern $bSecp224r1 :: CBytes
$mSecp224r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp224r1 = "secp224r1"

pattern Secp256k1 :: ECGroup
pattern $bSecp256k1 :: CBytes
$mSecp256k1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp256k1 = "secp256k1"

pattern Secp256r1 :: ECGroup
pattern $bSecp256r1 :: CBytes
$mSecp256r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp256r1 = "secp256r1"

pattern Secp384r1 :: ECGroup
pattern $bSecp384r1 :: CBytes
$mSecp384r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp384r1 = "secp384r1"

pattern Secp521r1 :: ECGroup
pattern $bSecp521r1 :: CBytes
$mSecp521r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Secp521r1 = "secp521r1"

pattern Brainpool160r1 :: ECGroup
pattern $bBrainpool160r1 :: CBytes
$mBrainpool160r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Brainpool160r1 = "brainpool160r1"

pattern Brainpool192r1 :: ECGroup
pattern $bBrainpool192r1 :: CBytes
$mBrainpool192r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Brainpool192r1 = "brainpool192r1"

pattern Brainpool224r1 :: ECGroup
pattern $bBrainpool224r1 :: CBytes
$mBrainpool224r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Brainpool224r1 = "brainpool224r1"

pattern Brainpool256r1 :: ECGroup
pattern $bBrainpool256r1 :: CBytes
$mBrainpool256r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Brainpool256r1 = "brainpool256r1"

pattern Brainpool320r1 :: ECGroup
pattern $bBrainpool320r1 :: CBytes
$mBrainpool320r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Brainpool320r1 = "brainpool320r1"

pattern Brainpool384r1 :: ECGroup
pattern $bBrainpool384r1 :: CBytes
$mBrainpool384r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Brainpool384r1 = "brainpool384r1"

pattern Brainpool512r1 :: ECGroup
pattern $bBrainpool512r1 :: CBytes
$mBrainpool512r1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Brainpool512r1 = "brainpool512r1"

pattern X962_p192v2 :: ECGroup
pattern $bX962_p192v2 :: CBytes
$mX962_p192v2 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
X962_p192v2 = "x962_p192v2"

pattern X962_p192v3 :: ECGroup
pattern $bX962_p192v3 :: CBytes
$mX962_p192v3 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
X962_p192v3 = "x962_p192v3"

pattern X962_p239v1 :: ECGroup
pattern $bX962_p239v1 :: CBytes
$mX962_p239v1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
X962_p239v1 = "x962_p239v1"

pattern X962_p239v2 :: ECGroup
pattern $bX962_p239v2 :: CBytes
$mX962_p239v2 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
X962_p239v2 = "x962_p239v2"

pattern X962_p239v3 :: ECGroup
pattern $bX962_p239v3 :: CBytes
$mX962_p239v3 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
X962_p239v3 = "x962_p239v3"

pattern Gost_256A :: ECGroup
pattern $bGost_256A :: CBytes
$mGost_256A :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Gost_256A = "gost_256A"

pattern Gost_512A :: ECGroup
pattern $bGost_512A :: CBytes
$mGost_512A :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Gost_512A = "gost_512A"

pattern Frp256v1 :: ECGroup
pattern $bFrp256v1 :: CBytes
$mFrp256v1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Frp256v1 = "frp256v1"

pattern Sm2p256v1 :: ECGroup
pattern $bSm2p256v1 :: CBytes
$mSm2p256v1 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
Sm2p256v1 = "sm2p256v1"

-- | Discrete Logarithm Group
type DLGroup = CBytes

pattern FFDHE_IETF_2048 :: DLGroup
pattern $bFFDHE_IETF_2048 :: CBytes
$mFFDHE_IETF_2048 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
FFDHE_IETF_2048 = "ffdhe/ietf/2048"

pattern FFDHE_IETF_3072 :: DLGroup
pattern $bFFDHE_IETF_3072 :: CBytes
$mFFDHE_IETF_3072 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
FFDHE_IETF_3072 = "ffdhe/ietf/3072"

pattern FFDHE_IETF_4096 :: DLGroup
pattern $bFFDHE_IETF_4096 :: CBytes
$mFFDHE_IETF_4096 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
FFDHE_IETF_4096 = "ffdhe/ietf/4096"

pattern FFDHE_IETF_6144 :: DLGroup
pattern $bFFDHE_IETF_6144 :: CBytes
$mFFDHE_IETF_6144 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
FFDHE_IETF_6144 = "ffdhe/ietf/6144"

pattern FFDHE_IETF_8192 :: DLGroup
pattern $bFFDHE_IETF_8192 :: CBytes
$mFFDHE_IETF_8192 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
FFDHE_IETF_8192 = "ffdhe/ietf/8192"

pattern MODP_IETF_1024 :: DLGroup
pattern $bMODP_IETF_1024 :: CBytes
$mMODP_IETF_1024 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_IETF_1024 = "modp/ietf/1024"

pattern MODP_IETF_1536 :: DLGroup
pattern $bMODP_IETF_1536 :: CBytes
$mMODP_IETF_1536 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_IETF_1536 = "modp/ietf/1536"

pattern MODP_IETF_2048 :: DLGroup
pattern $bMODP_IETF_2048 :: CBytes
$mMODP_IETF_2048 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_IETF_2048 = "modp/ietf/2048"

pattern MODP_IETF_3072 :: DLGroup
pattern $bMODP_IETF_3072 :: CBytes
$mMODP_IETF_3072 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_IETF_3072 = "modp/ietf/3072"

pattern MODP_IETF_4096 :: DLGroup
pattern $bMODP_IETF_4096 :: CBytes
$mMODP_IETF_4096 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_IETF_4096 = "modp/ietf/4096"

pattern MODP_IETF_6144 :: DLGroup
pattern $bMODP_IETF_6144 :: CBytes
$mMODP_IETF_6144 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_IETF_6144 = "modp/ietf/6144"

pattern MODP_IETF_8192 :: DLGroup
pattern $bMODP_IETF_8192 :: CBytes
$mMODP_IETF_8192 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_IETF_8192 = "modp/ietf/8192"

pattern MODP_SRP_1024 :: DLGroup
pattern $bMODP_SRP_1024 :: CBytes
$mMODP_SRP_1024 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_SRP_1024 = "modp/srp/1024"

pattern MODP_SRP_1536 :: DLGroup
pattern $bMODP_SRP_1536 :: CBytes
$mMODP_SRP_1536 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_SRP_1536 = "modp/srp/1536"

pattern MODP_SRP_2048 :: DLGroup
pattern $bMODP_SRP_2048 :: CBytes
$mMODP_SRP_2048 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_SRP_2048 = "modp/srp/2048"

pattern MODP_SRP_3072 :: DLGroup
pattern $bMODP_SRP_3072 :: CBytes
$mMODP_SRP_3072 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_SRP_3072 = "modp/srp/3072"

pattern MODP_SRP_4096 :: DLGroup
pattern $bMODP_SRP_4096 :: CBytes
$mMODP_SRP_4096 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_SRP_4096 = "modp/srp/4096"

pattern MODP_SRP_6144 :: DLGroup
pattern $bMODP_SRP_6144 :: CBytes
$mMODP_SRP_6144 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_SRP_6144 = "modp/srp/6144"

pattern MODP_SRP_8192 :: DLGroup
pattern $bMODP_SRP_8192 :: CBytes
$mMODP_SRP_8192 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
MODP_SRP_8192 = "modp/srp/8192"

pattern DSA_JCE_1024 :: DLGroup
pattern $bDSA_JCE_1024 :: CBytes
$mDSA_JCE_1024 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
DSA_JCE_1024 = "dsa/jce/1024"

pattern DSA_BOTAN_2048 :: DLGroup
pattern $bDSA_BOTAN_2048 :: CBytes
$mDSA_BOTAN_2048 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
DSA_BOTAN_2048 = "dsa/botan/2048"

pattern DSA_BOTAN_3072 :: DLGroup
pattern $bDSA_BOTAN_3072 :: CBytes
$mDSA_BOTAN_3072 :: forall r. CBytes -> (Void# -> r) -> (Void# -> r) -> r
DSA_BOTAN_3072 = "dsa/botan/3072"

---------------------------
-- Private Key Functions --
---------------------------

-- | An opaque data type for a private-public key pair.
newtype PrivKey = PrivKey BotanStruct
    deriving (Int -> PrivKey -> ShowS
[PrivKey] -> ShowS
PrivKey -> String
(Int -> PrivKey -> ShowS)
-> (PrivKey -> String) -> ([PrivKey] -> ShowS) -> Show PrivKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PrivKey] -> ShowS
$cshowList :: [PrivKey] -> ShowS
show :: PrivKey -> String
$cshow :: PrivKey -> String
showsPrec :: Int -> PrivKey -> ShowS
$cshowsPrec :: Int -> PrivKey -> ShowS
Show, (forall x. PrivKey -> Rep PrivKey x)
-> (forall x. Rep PrivKey x -> PrivKey) -> Generic PrivKey
forall x. Rep PrivKey x -> PrivKey
forall x. PrivKey -> Rep PrivKey x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PrivKey x -> PrivKey
$cfrom :: forall x. PrivKey -> Rep PrivKey x
Generic)
    deriving anyclass Int -> PrivKey -> Builder ()
(Int -> PrivKey -> Builder ()) -> Print PrivKey
forall a. (Int -> a -> Builder ()) -> Print a
toUTF8BuilderP :: Int -> PrivKey -> Builder ()
$ctoUTF8BuilderP :: Int -> PrivKey -> Builder ()
T.Print

-- | Pass 'PrivKey' to FFI.
withPrivKey :: HasCallStack
            => PrivKey -> (BotanStructT -> IO r) -> IO r
{-# INLINABLE withPrivKey  #-}
withPrivKey :: PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey (PrivKey BotanStruct
key) = BotanStruct -> (BotanStructT -> IO r) -> IO r
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
key

-- | Creating a new key pair.
--
newKeyPair :: HasCallStack
           => KeyType   -- ^ Algorithm name and some algorithm specific arguments.
           -> RNG
           -> IO (PrivKey, PubKey)
{-# INLINABLE newKeyPair  #-}
newKeyPair :: KeyType -> RNG -> IO (PrivKey, PubKey)
newKeyPair KeyType
kt RNG
rng = do
    PrivKey
priv <- HasCallStack => KeyType -> RNG -> IO PrivKey
KeyType -> RNG -> IO PrivKey
newPrivKey KeyType
kt RNG
rng
    let !pub :: PubKey
pub = PrivKey -> PubKey
privKeyToPubKey PrivKey
priv
    (PrivKey, PubKey) -> IO (PrivKey, PubKey)
forall (m :: * -> *) a. Monad m => a -> m a
return (PrivKey
priv, PubKey
pub)

-- | Creating a private key.
--
-- Creating a private key requires two things:
--
-- * a source of random numbers
-- * some algorithm specific arguments that define the security level of the resulting key.
--
newPrivKey :: HasCallStack
           => KeyType   -- ^ Algorithm name and some algorithm specific arguments.
           -> RNG
           -> IO PrivKey
{-# INLINABLE newPrivKey  #-}
newPrivKey :: KeyType -> RNG -> IO PrivKey
newPrivKey KeyType
keyTyp RNG
rng =
    RNG -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
rng' ->
    CBytes -> (Ptr Word8 -> IO PrivKey) -> IO PrivKey
forall a. CBytes -> (Ptr Word8 -> IO a) -> IO a
CB.withCBytes CBytes
algo ((Ptr Word8 -> IO PrivKey) -> IO PrivKey)
-> (Ptr Word8 -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
algo' ->
    CBytes -> (Ptr Word8 -> IO PrivKey) -> IO PrivKey
forall a. CBytes -> (Ptr Word8 -> IO a) -> IO a
CB.withCBytes CBytes
args ((Ptr Word8 -> IO PrivKey) -> IO PrivKey)
-> (Ptr Word8 -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
args' ->
        BotanStruct -> PrivKey
PrivKey (BotanStruct -> PrivKey) -> IO BotanStruct -> IO PrivKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(Ptr BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct'
            (\ Ptr BotanStructT
key -> Ptr BotanStructT
-> Ptr Word8 -> Ptr Word8 -> BotanStructT -> IO CInt
botan_privkey_create Ptr BotanStructT
key Ptr Word8
algo' Ptr Word8
args' BotanStructT
rng')
            FunPtr (BotanStructT -> IO ())
botan_privkey_destroy
    where
        (CBytes
algo, CBytes
args) = KeyType -> (CBytes, CBytes)
keyTypeToCBytes KeyType
keyTyp

-- | Load a private key. If the key is encrypted, password will be used to attempt decryption.
loadPrivKey :: HasCallStack =>
    RNG ->
    V.Bytes ->
    -- | Password.
    CBytes ->
    IO PrivKey
{-# INLINABLE loadPrivKey  #-}
loadPrivKey :: RNG -> Bytes -> CBytes -> IO PrivKey
loadPrivKey RNG
rng Bytes
buf CBytes
passwd =
    RNG -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
rng' ->
    Bytes -> (BA# Word8 -> Int -> Int -> IO PrivKey) -> IO PrivKey
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
buf ((BA# Word8 -> Int -> Int -> IO PrivKey) -> IO PrivKey)
-> (BA# Word8 -> Int -> Int -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
buf' Int
off Int
len ->
    CBytes -> (BA# Word8 -> IO PrivKey) -> IO PrivKey
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
passwd ((BA# Word8 -> IO PrivKey) -> IO PrivKey)
-> (BA# Word8 -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
passwd' ->
        BotanStruct -> PrivKey
PrivKey (BotanStruct -> PrivKey) -> IO BotanStruct -> IO PrivKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
            (\ MBA# BotanStructT
key -> MBA# BotanStructT
-> BotanStructT -> BA# Word8 -> Int -> Int -> BA# Word8 -> IO CInt
hs_botan_privkey_load MBA# BotanStructT
key BotanStructT
rng' BA# Word8
buf' Int
off Int
len BA# Word8
passwd')
            FunPtr (BotanStructT -> IO ())
botan_privkey_destroy

-- | Get the algorithm name of a private key.
privKeyAlgoName :: PrivKey -> IO T.Text
{-# INLINABLE privKeyAlgoName  #-}
privKeyAlgoName :: PrivKey -> IO Text
privKeyAlgoName PrivKey
key =
    PrivKey -> (BotanStructT -> IO Text) -> IO Text
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO Text) -> IO Text)
-> (BotanStructT -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Text
allocBotanBufferUTF8Unsafe Int
16 ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text)
-> (BotanStructT
    -> MBA# BotanStructT -> MBA# BotanStructT -> IO CInt)
-> BotanStructT
-> IO Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BotanStructT -> MBA# BotanStructT -> MBA# BotanStructT -> IO CInt
botan_privkey_algo_name

-- | Export a private key in DER binary format.
exportPrivKeyDER :: HasCallStack => PrivKey -> V.Bytes
{-# INLINABLE exportPrivKeyDER  #-}
exportPrivKeyDER :: PrivKey -> Bytes
exportPrivKeyDER PrivKey
key = IO Bytes -> Bytes
forall a. IO a -> a
unsafePerformIO (IO Bytes -> Bytes) -> IO Bytes -> Bytes
forall a b. (a -> b) -> a -> b
$
    PrivKey -> (BotanStructT -> IO Bytes) -> IO Bytes
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' ->
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe Int
V.smallChunkSize ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
buf MBA# BotanStructT
siz ->
    BotanStructT
-> MBA# BotanStructT -> MBA# BotanStructT -> Word32 -> IO CInt
botan_privkey_export BotanStructT
key' MBA# BotanStructT
buf MBA# BotanStructT
siz Word32
0

-- | Export a private key in PEM textual format.
exportPrivKeyPEM :: HasCallStack => PrivKey -> T.Text
{-# INLINABLE exportPrivKeyPEM  #-}
exportPrivKeyPEM :: PrivKey -> Text
exportPrivKeyPEM PrivKey
key = IO Text -> Text
forall a. IO a -> a
unsafePerformIO (IO Text -> Text) -> IO Text -> Text
forall a b. (a -> b) -> a -> b
$
    PrivKey -> (BotanStructT -> IO Text) -> IO Text
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO Text) -> IO Text)
-> (BotanStructT -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' ->
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Text
allocBotanBufferUTF8Unsafe Int
V.smallChunkSize ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
buf MBA# BotanStructT
siz ->
    BotanStructT
-> MBA# BotanStructT -> MBA# BotanStructT -> Word32 -> IO CInt
botan_privkey_export BotanStructT
key' MBA# BotanStructT
buf MBA# BotanStructT
siz Word32
1

-- | Export a private key with password.
exportPrivKeyEncryptedDER :: HasCallStack
                          => PrivKey -> RNG
                          -> CBytes        -- ^ password
                          -> IO V.Bytes
{-# INLINABLE exportPrivKeyEncryptedDER  #-}
exportPrivKeyEncryptedDER :: PrivKey -> RNG -> CBytes -> IO Bytes
exportPrivKeyEncryptedDER PrivKey
key RNG
rng CBytes
pwd =
    PrivKey -> (BotanStructT -> IO Bytes) -> IO Bytes
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' ->
    RNG -> (BotanStructT -> IO Bytes) -> IO Bytes
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
rng' ->
    CBytes -> (BA# Word8 -> IO Bytes) -> IO Bytes
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
pwd ((BA# Word8 -> IO Bytes) -> IO Bytes)
-> (BA# Word8 -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
pwd' ->
    CBytes -> (BA# Word8 -> IO Bytes) -> IO Bytes
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
"" ((BA# Word8 -> IO Bytes) -> IO Bytes)
-> (BA# Word8 -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
pbe' ->   -- currently ignored
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe Int
V.smallChunkSize ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
buf MBA# BotanStructT
siz ->
    BotanStructT
-> MBA# BotanStructT
-> MBA# BotanStructT
-> BotanStructT
-> BA# Word8
-> BA# Word8
-> Word32
-> IO CInt
botan_privkey_export_encrypted BotanStructT
key' MBA# BotanStructT
buf MBA# BotanStructT
siz BotanStructT
rng' BA# Word8
pwd' BA# Word8
pbe' Word32
0

-- | Export a private key with password in PEM textual format.
exportPrivKeyEncryptedPEM :: HasCallStack
                          => PrivKey -> RNG
                          -> CBytes        -- ^ password
                          -> IO T.Text
{-# INLINABLE exportPrivKeyEncryptedPEM  #-}
exportPrivKeyEncryptedPEM :: PrivKey -> RNG -> CBytes -> IO Text
exportPrivKeyEncryptedPEM PrivKey
key RNG
rng CBytes
pwd =
    PrivKey -> (BotanStructT -> IO Text) -> IO Text
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO Text) -> IO Text)
-> (BotanStructT -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' ->
    RNG -> (BotanStructT -> IO Text) -> IO Text
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO Text) -> IO Text)
-> (BotanStructT -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
rng' ->
    CBytes -> (BA# Word8 -> IO Text) -> IO Text
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
pwd ((BA# Word8 -> IO Text) -> IO Text)
-> (BA# Word8 -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
pwd' ->
    CBytes -> (BA# Word8 -> IO Text) -> IO Text
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
"" ((BA# Word8 -> IO Text) -> IO Text)
-> (BA# Word8 -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
pbe' ->   -- currently ignored
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Text
allocBotanBufferUTF8Unsafe Int
V.smallChunkSize ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
buf MBA# BotanStructT
siz ->
    BotanStructT
-> MBA# BotanStructT
-> MBA# BotanStructT
-> BotanStructT
-> BA# Word8
-> BA# Word8
-> Word32
-> IO CInt
botan_privkey_export_encrypted BotanStructT
key' MBA# BotanStructT
buf MBA# BotanStructT
siz BotanStructT
rng' BA# Word8
pwd' BA# Word8
pbe' Word32
1

-- | Export a public key from a given key pair.
privKeyToPubKey :: PrivKey -> PubKey
{-# INLINABLE privKeyToPubKey  #-}
privKeyToPubKey :: PrivKey -> PubKey
privKeyToPubKey (PrivKey BotanStruct
priv) = IO PubKey -> PubKey
forall a. IO a -> a
unsafePerformIO (IO PubKey -> PubKey) -> IO PubKey -> PubKey
forall a b. (a -> b) -> a -> b
$ do
    BotanStruct -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
priv ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
priv' ->
        BotanStruct -> PubKey
PubKey (BotanStruct -> PubKey) -> IO BotanStruct -> IO PubKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (MBA# BotanStructT -> BotanStructT -> IO CInt
`botan_privkey_export_pubkey` BotanStructT
priv') FunPtr (BotanStructT -> IO ())
botan_privkey_destroy

-- | Read an algorithm specific field from the key pair object.
privKeyParam :: HasCallStack
             => PrivKey      -- ^ key
             -> CBytes       -- ^ field name
             -> MPI
{-# INLINABLE privKeyParam  #-}
privKeyParam :: PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
name =
    (BotanStructT -> IO ()) -> MPI
forall a. (BotanStructT -> IO a) -> MPI
unsafeNewMPI ((BotanStructT -> IO ()) -> MPI) -> (BotanStructT -> IO ()) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
mp ->
    PrivKey -> (BotanStructT -> IO ()) -> IO ()
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO ()) -> IO ())
-> (BotanStructT -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' -> do
    IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (CBytes -> (BA# Word8 -> IO CInt) -> IO CInt
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
name (BotanStructT -> BotanStructT -> BA# Word8 -> IO CInt
botan_privkey_get_field BotanStructT
mp BotanStructT
key'))

-- | A newtype wrapper.
newtype PubKey = PubKey BotanStruct
    deriving (Int -> PubKey -> ShowS
[PubKey] -> ShowS
PubKey -> String
(Int -> PubKey -> ShowS)
-> (PubKey -> String) -> ([PubKey] -> ShowS) -> Show PubKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PubKey] -> ShowS
$cshowList :: [PubKey] -> ShowS
show :: PubKey -> String
$cshow :: PubKey -> String
showsPrec :: Int -> PubKey -> ShowS
$cshowsPrec :: Int -> PubKey -> ShowS
Show, PubKey -> PubKey -> Bool
(PubKey -> PubKey -> Bool)
-> (PubKey -> PubKey -> Bool) -> Eq PubKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PubKey -> PubKey -> Bool
$c/= :: PubKey -> PubKey -> Bool
== :: PubKey -> PubKey -> Bool
$c== :: PubKey -> PubKey -> Bool
Eq, Eq PubKey
Eq PubKey
-> (PubKey -> PubKey -> Ordering)
-> (PubKey -> PubKey -> Bool)
-> (PubKey -> PubKey -> Bool)
-> (PubKey -> PubKey -> Bool)
-> (PubKey -> PubKey -> Bool)
-> (PubKey -> PubKey -> PubKey)
-> (PubKey -> PubKey -> PubKey)
-> Ord PubKey
PubKey -> PubKey -> Bool
PubKey -> PubKey -> Ordering
PubKey -> PubKey -> PubKey
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 :: PubKey -> PubKey -> PubKey
$cmin :: PubKey -> PubKey -> PubKey
max :: PubKey -> PubKey -> PubKey
$cmax :: PubKey -> PubKey -> PubKey
>= :: PubKey -> PubKey -> Bool
$c>= :: PubKey -> PubKey -> Bool
> :: PubKey -> PubKey -> Bool
$c> :: PubKey -> PubKey -> Bool
<= :: PubKey -> PubKey -> Bool
$c<= :: PubKey -> PubKey -> Bool
< :: PubKey -> PubKey -> Bool
$c< :: PubKey -> PubKey -> Bool
compare :: PubKey -> PubKey -> Ordering
$ccompare :: PubKey -> PubKey -> Ordering
$cp1Ord :: Eq PubKey
Ord, (forall x. PubKey -> Rep PubKey x)
-> (forall x. Rep PubKey x -> PubKey) -> Generic PubKey
forall x. Rep PubKey x -> PubKey
forall x. PubKey -> Rep PubKey x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PubKey x -> PubKey
$cfrom :: forall x. PubKey -> Rep PubKey x
Generic)
    deriving anyclass Int -> PubKey -> Builder ()
(Int -> PubKey -> Builder ()) -> Print PubKey
forall a. (Int -> a -> Builder ()) -> Print a
toUTF8BuilderP :: Int -> PubKey -> Builder ()
$ctoUTF8BuilderP :: Int -> PubKey -> Builder ()
T.Print

-- | Unsafe construct a 'PubKey' from a botan struct.
botanStructToPubKey :: BotanStruct -> PubKey
{-# INLINABLE botanStructToPubKey  #-}
botanStructToPubKey :: BotanStruct -> PubKey
botanStructToPubKey = BotanStruct -> PubKey
PubKey

-- | Pass 'PubKey' to FFI.
withPubKey :: PubKey -> (BotanStructT -> IO r) -> IO r
{-# INLINABLE withPubKey  #-}
withPubKey :: PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey (PubKey BotanStruct
key) = BotanStruct -> (BotanStructT -> IO r) -> IO r
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
key

-- | Load a publickey.
loadPubKey :: HasCallStack => V.Bytes -> IO PubKey
{-# INLINABLE loadPubKey  #-}
loadPubKey :: Bytes -> IO PubKey
loadPubKey Bytes
buf = do
    Bytes -> (BA# Word8 -> Int -> Int -> IO PubKey) -> IO PubKey
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
buf ((BA# Word8 -> Int -> Int -> IO PubKey) -> IO PubKey)
-> (BA# Word8 -> Int -> Int -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
buf' Int
off Int
len ->
        BotanStruct -> PubKey
PubKey (BotanStruct -> PubKey) -> IO BotanStruct -> IO PubKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (\ MBA# BotanStructT
pubKey -> MBA# BotanStructT -> BA# Word8 -> Int -> Int -> IO CInt
hs_botan_pubkey_load MBA# BotanStructT
pubKey BA# Word8
buf' Int
off Int
len) FunPtr (BotanStructT -> IO ())
botan_pubkey_destroy

-- | Export a public key in DER binary format..
exportPubKeyDER :: HasCallStack => PubKey -> V.Bytes
{-# INLINABLE exportPubKeyDER  #-}
exportPubKeyDER :: PubKey -> Bytes
exportPubKeyDER PubKey
pubKey = IO Bytes -> Bytes
forall a. IO a -> a
unsafePerformIO (IO Bytes -> Bytes) -> IO Bytes -> Bytes
forall a b. (a -> b) -> a -> b
$
    PubKey -> (BotanStructT -> IO Bytes) -> IO Bytes
forall r. PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey PubKey
pubKey ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
pubKey' ->
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe Int
V.smallChunkSize ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
buf MBA# BotanStructT
siz ->
    BotanStructT
-> MBA# BotanStructT -> MBA# BotanStructT -> Word32 -> IO CInt
botan_pubkey_export BotanStructT
pubKey' MBA# BotanStructT
buf MBA# BotanStructT
siz Word32
0

-- | Export a public key in PEM textual format.
exportPubKeyPEM :: HasCallStack => PubKey -> T.Text
{-# INLINABLE exportPubKeyPEM  #-}
exportPubKeyPEM :: PubKey -> Text
exportPubKeyPEM PubKey
pubKey = IO Text -> Text
forall a. IO a -> a
unsafePerformIO (IO Text -> Text) -> IO Text -> Text
forall a b. (a -> b) -> a -> b
$
    PubKey -> (BotanStructT -> IO Text) -> IO Text
forall r. PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey PubKey
pubKey ((BotanStructT -> IO Text) -> IO Text)
-> (BotanStructT -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
pubKey' ->
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Text
allocBotanBufferUTF8Unsafe Int
V.smallChunkSize ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Text
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
buf MBA# BotanStructT
siz ->
    BotanStructT
-> MBA# BotanStructT -> MBA# BotanStructT -> Word32 -> IO CInt
botan_pubkey_export BotanStructT
pubKey' MBA# BotanStructT
buf MBA# BotanStructT
siz Word32
1

-- | Get the algorithm name of a public key.
pubKeyAlgoName :: PubKey -> CBytes
{-# INLINABLE pubKeyAlgoName  #-}
pubKeyAlgoName :: PubKey -> CBytes
pubKeyAlgoName PubKey
pubKey = IO CBytes -> CBytes
forall a. IO a -> a
unsafePerformIO (IO CBytes -> CBytes) -> IO CBytes -> CBytes
forall a b. (a -> b) -> a -> b
$
    PubKey -> (BotanStructT -> IO CBytes) -> IO CBytes
forall r. PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey PubKey
pubKey ((BotanStructT -> IO CBytes) -> IO CBytes)
-> (BotanStructT -> IO CBytes) -> IO CBytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
pubKey' ->
        Bytes -> CBytes
CB.fromBytes (Bytes -> CBytes) -> IO Bytes -> IO CBytes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe Int
16
            (BotanStructT -> MBA# BotanStructT -> MBA# BotanStructT -> IO CInt
botan_pubkey_algo_name BotanStructT
pubKey')

-- | Estimate the strength of a public key.
estStrength :: PubKey -> Int
{-# INLINABLE estStrength  #-}
estStrength :: PubKey -> Int
estStrength PubKey
pubKey = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
    PubKey -> (BotanStructT -> IO Int) -> IO Int
forall r. PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey PubKey
pubKey ((BotanStructT -> IO Int) -> IO Int)
-> (BotanStructT -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
pubKey' -> do
        (CSize
a, ()
_) <- forall b.
Prim CSize =>
(MBA# BotanStructT -> IO b) -> IO (CSize, b)
forall a b. Prim a => (MBA# BotanStructT -> IO b) -> IO (a, b)
allocPrimUnsafe @CSize ((MBA# BotanStructT -> IO ()) -> IO (CSize, ()))
-> (MBA# BotanStructT -> IO ()) -> IO (CSize, ())
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
est ->
            IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> MBA# BotanStructT -> IO CInt
botan_pubkey_estimated_strength BotanStructT
pubKey' MBA# BotanStructT
est)
        Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
a)

-- | Fingerprint a given publickey.
fingerPrintPubKey :: PubKey -> HashType -> V.Bytes
{-# INLINABLE fingerPrintPubKey  #-}
fingerPrintPubKey :: PubKey -> HashType -> Bytes
fingerPrintPubKey PubKey
pubKey HashType
ht = IO Bytes -> Bytes
forall a. IO a -> a
unsafePerformIO (IO Bytes -> Bytes) -> IO Bytes -> Bytes
forall a b. (a -> b) -> a -> b
$
    PubKey -> (BotanStructT -> IO Bytes) -> IO Bytes
forall r. PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey PubKey
pubKey ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
pubKey' ->
    CBytes -> (BA# Word8 -> IO Bytes) -> IO Bytes
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe (HashType -> CBytes
hashTypeToCBytes HashType
ht) ((BA# Word8 -> IO Bytes) -> IO Bytes)
-> (BA# Word8 -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
hash' ->
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe Int
V.smallChunkSize ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
buf MBA# BotanStructT
siz ->
    BotanStructT
-> BA# Word8 -> MBA# BotanStructT -> MBA# BotanStructT -> IO CInt
botan_pubkey_fingerprint BotanStructT
pubKey' BA# Word8
hash' MBA# BotanStructT
buf MBA# BotanStructT
siz

-- | Read an algorithm specific field from the public key object.
pubKeyParam :: PubKey       -- ^ key
            -> CBytes       -- ^ field name
            -> MPI
{-# INLINABLE pubKeyParam  #-}
pubKeyParam :: PubKey -> CBytes -> MPI
pubKeyParam PubKey
pubKey CBytes
name =
    (BotanStructT -> IO ()) -> MPI
forall a. (BotanStructT -> IO a) -> MPI
unsafeNewMPI ((BotanStructT -> IO ()) -> MPI) -> (BotanStructT -> IO ()) -> MPI
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
mp ->
    PubKey -> (BotanStructT -> IO ()) -> IO ()
forall r. PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey PubKey
pubKey ((BotanStructT -> IO ()) -> IO ())
-> (BotanStructT -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
pubKey' -> do
    IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (CBytes -> (BA# Word8 -> IO CInt) -> IO CInt
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
name (BotanStructT -> BotanStructT -> BA# Word8 -> IO CInt
botan_pubkey_get_field BotanStructT
mp BotanStructT
pubKey'))

----------------------------
-- RSA specific functions --
----------------------------


-- | Get RSA parameters
--
-- * Set p to the first RSA prime.
-- * Set q to the second RSA prime.
-- * Set n to the RSA modulus.
-- * Set d to the RSA private exponent.
-- * Set e to the RSA public exponent.
--
getRSAParams :: PrivKey
             -> (MPI, MPI, MPI, MPI, MPI)   -- ^ (p, q, n, d, e)
{-# INLINABLE getRSAParams  #-}
getRSAParams :: PrivKey -> (MPI, MPI, MPI, MPI, MPI)
getRSAParams PrivKey
key = (MPI
p, MPI
q, MPI
n, MPI
d, MPI
e)
  where
    !p :: MPI
p = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"p"
    !q :: MPI
q = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"q"
    !n :: MPI
n = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"n"
    !d :: MPI
d = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"d"
    !e :: MPI
e = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"e"

-- | Get RSA Public parameters
--
-- * Set n to the RSA modulus.
-- * Set e to the RSA public exponent.
--
getRSAPubParams :: PubKey
                -> (MPI, MPI)   -- ^ (n, e)
{-# INLINABLE getRSAPubParams  #-}
getRSAPubParams :: PubKey -> (MPI, MPI)
getRSAPubParams PubKey
key = (MPI
n, MPI
e)
  where
    !n :: MPI
n = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"n"
    !e :: MPI
e = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"e"

-- | Initialize a RSA key pair using arguments p, q, and e.
newRSAPrivKey :: HasCallStack => MPI -> MPI -> MPI -> PrivKey
{-# INLINABLE newRSAPrivKey  #-}
newRSAPrivKey :: MPI -> MPI -> MPI -> PrivKey
newRSAPrivKey MPI
p MPI
q MPI
e =
    MPI -> (BotanStructT -> IO PrivKey) -> PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
p ((BotanStructT -> IO PrivKey) -> PrivKey)
-> (BotanStructT -> IO PrivKey) -> PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
p' ->
    MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
q ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
q' ->
    MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
e ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
e' ->
        BotanStruct -> PrivKey
PrivKey (BotanStruct -> PrivKey) -> IO BotanStruct -> IO PrivKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
            (\ MBA# BotanStructT
key -> MBA# BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_privkey_load_rsa MBA# BotanStructT
key BotanStructT
p' BotanStructT
q' BotanStructT
e')
            FunPtr (BotanStructT -> IO ())
botan_privkey_destroy

-- | Initialize a public RSA key using arguments n and e.
newRSAPubKey :: HasCallStack => MPI -> MPI -> PubKey
{-# INLINABLE newRSAPubKey  #-}
newRSAPubKey :: MPI -> MPI -> PubKey
newRSAPubKey MPI
n MPI
e = do
    MPI -> (BotanStructT -> IO PubKey) -> PubKey
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
n ((BotanStructT -> IO PubKey) -> PubKey)
-> (BotanStructT -> IO PubKey) -> PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
n' ->
        MPI -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
e ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
e' ->
            BotanStruct -> PubKey
PubKey (BotanStruct -> PubKey) -> IO BotanStruct -> IO PubKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (\ MBA# BotanStructT
pubKey -> MBA# BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_pubkey_load_rsa MBA# BotanStructT
pubKey BotanStructT
n' BotanStructT
e') FunPtr (BotanStructT -> IO ())
botan_pubkey_destroy

----------------------------
-- DSA specific functions --
----------------------------

-- | Get DSA parameters
--
-- * Set p, q, g to group parameters
-- * Set x to the private key
--
getDSAPrivParams :: PrivKey
                 -> (MPI, MPI, MPI, MPI)   -- ^ (p, q, g, x)
{-# INLINABLE getDSAPrivParams  #-}
getDSAPrivParams :: PrivKey -> (MPI, MPI, MPI, MPI)
getDSAPrivParams PrivKey
key = (MPI
p, MPI
q, MPI
g, MPI
x)
  where
    !p :: MPI
p = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"p"
    !q :: MPI
q = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"q"
    !g :: MPI
g = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"g"
    !x :: MPI
x = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"x"

-- | Initialize a DSA key pair using arguments p, q, g and x.
newDSAPrivKey :: HasCallStack => MPI -> MPI -> MPI -> MPI -> PrivKey
{-# INLINABLE newDSAPrivKey  #-}
newDSAPrivKey :: MPI -> MPI -> MPI -> MPI -> PrivKey
newDSAPrivKey MPI
p MPI
q MPI
g MPI
x =
    MPI -> (BotanStructT -> IO PrivKey) -> PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
p ((BotanStructT -> IO PrivKey) -> PrivKey)
-> (BotanStructT -> IO PrivKey) -> PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
p' ->
    MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
q ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
q' ->
    MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
g ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
g' ->
    MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
x ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
x' ->
        BotanStruct -> PrivKey
PrivKey (BotanStruct -> PrivKey) -> IO BotanStruct -> IO PrivKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
            (\ MBA# BotanStructT
key -> MBA# BotanStructT
-> BotanStructT
-> BotanStructT
-> BotanStructT
-> BotanStructT
-> IO CInt
botan_privkey_load_dsa MBA# BotanStructT
key BotanStructT
p' BotanStructT
q' BotanStructT
g' BotanStructT
x')
            FunPtr (BotanStructT -> IO ())
botan_privkey_destroy

-- | Get DSA parameters
--
-- * Set p, q, g to group parameters
-- * Set y to the public key
--
getDSAPubParams :: PubKey
                -> (MPI, MPI, MPI, MPI)   -- ^ (p, q, g, y)
{-# INLINABLE getDSAPubParams  #-}
getDSAPubParams :: PubKey -> (MPI, MPI, MPI, MPI)
getDSAPubParams PubKey
key = (MPI
p, MPI
q, MPI
g, MPI
y)
  where
    !p :: MPI
p = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"p"
    !q :: MPI
q = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"q"
    !g :: MPI
g = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"g"
    !y :: MPI
y = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"y"

-- | Initialize a DSA public key using arguments p, q, g and y.
newDSAPubKey :: HasCallStack => MPI -> MPI -> MPI -> MPI -> PubKey
{-# INLINABLE newDSAPubKey  #-}
newDSAPubKey :: MPI -> MPI -> MPI -> MPI -> PubKey
newDSAPubKey MPI
p MPI
q MPI
g MPI
y =
    MPI -> (BotanStructT -> IO PubKey) -> PubKey
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
p ((BotanStructT -> IO PubKey) -> PubKey)
-> (BotanStructT -> IO PubKey) -> PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
p' ->
    MPI -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
q ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
q' ->
    MPI -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
g ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
g' ->
    MPI -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
y ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
y' ->
        BotanStruct -> PubKey
PubKey (BotanStruct -> PubKey) -> IO BotanStruct -> IO PubKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
            (\ MBA# BotanStructT
key -> MBA# BotanStructT
-> BotanStructT
-> BotanStructT
-> BotanStructT
-> BotanStructT
-> IO CInt
botan_pubkey_load_dsa MBA# BotanStructT
key BotanStructT
p' BotanStructT
q' BotanStructT
g' BotanStructT
y')
            FunPtr (BotanStructT -> IO ())
botan_pubkey_destroy

--------------------------------
-- ElGamal specific functions --
--------------------------------

-- | Get ElGamal parameters
--
-- * Set p, g to group parameters
-- * Set x to the private key
--
getElGamalPrivParams :: PrivKey
                 -> (MPI, MPI, MPI)   -- ^ (p, g, x)
{-# INLINABLE getElGamalPrivParams  #-}
getElGamalPrivParams :: PrivKey -> (MPI, MPI, MPI)
getElGamalPrivParams PrivKey
key = (MPI
p, MPI
g, MPI
x)
  where
    !p :: MPI
p = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"p"
    !g :: MPI
g = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"g"
    !x :: MPI
x = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"x"

newElGamalPrivKey :: HasCallStack => MPI -> MPI -> MPI -> PrivKey
{-# INLINABLE newElGamalPrivKey  #-}
newElGamalPrivKey :: MPI -> MPI -> MPI -> PrivKey
newElGamalPrivKey MPI
p MPI
g MPI
x =
    MPI -> (BotanStructT -> IO PrivKey) -> PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
p ((BotanStructT -> IO PrivKey) -> PrivKey)
-> (BotanStructT -> IO PrivKey) -> PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
p' ->
    MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
g ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
g' ->
    MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
x ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
x' ->
        BotanStruct -> PrivKey
PrivKey (BotanStruct -> PrivKey) -> IO BotanStruct -> IO PrivKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
            (\ MBA# BotanStructT
key -> MBA# BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_privkey_load_elgamal MBA# BotanStructT
key BotanStructT
p' BotanStructT
g' BotanStructT
x')
            FunPtr (BotanStructT -> IO ())
botan_privkey_destroy

-- | Get ElGamal parameters
--
-- * Set p, g to group parameters
-- * Set y to the public key
--
getElGamalPubParams :: PubKey
                    -> (MPI, MPI, MPI)   -- ^ (p, g, y)
{-# INLINABLE getElGamalPubParams  #-}
getElGamalPubParams :: PubKey -> (MPI, MPI, MPI)
getElGamalPubParams PubKey
key = (MPI
p, MPI
g, MPI
y)
  where
    !p :: MPI
p = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"p"
    !g :: MPI
g = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"g"
    !y :: MPI
y = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"y"

newElGamalPubKey :: HasCallStack => MPI -> MPI -> MPI -> PubKey
{-# INLINABLE newElGamalPubKey  #-}
newElGamalPubKey :: MPI -> MPI -> MPI -> PubKey
newElGamalPubKey MPI
p MPI
g MPI
y =
    MPI -> (BotanStructT -> IO PubKey) -> PubKey
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
p ((BotanStructT -> IO PubKey) -> PubKey)
-> (BotanStructT -> IO PubKey) -> PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
p' ->
    MPI -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
g ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
g' ->
    MPI -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
y ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
y' ->
        BotanStruct -> PubKey
PubKey (BotanStruct -> PubKey) -> IO BotanStruct -> IO PubKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
                (\ MBA# BotanStructT
key -> MBA# BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_pubkey_load_elgamal MBA# BotanStructT
key BotanStructT
p' BotanStructT
g' BotanStructT
y')
                FunPtr (BotanStructT -> IO ())
botan_pubkey_destroy

---------------------------------------
-- Diffie-Hellman specific functions --
---------------------------------------

-- | Get Diffie-Hellman parameters
--
-- * Set p, g to group parameters
-- * Set x to the private key
--
getDHPrivParams :: PrivKey
                 -> (MPI, MPI, MPI)   -- ^ (p, g, x)
{-# INLINABLE getDHPrivParams  #-}
getDHPrivParams :: PrivKey -> (MPI, MPI, MPI)
getDHPrivParams PrivKey
key = (MPI
p, MPI
g, MPI
x)
  where
    !p :: MPI
p = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"p"
    !g :: MPI
g = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"g"
    !x :: MPI
x = HasCallStack => PrivKey -> CBytes -> MPI
PrivKey -> CBytes -> MPI
privKeyParam PrivKey
key CBytes
"x"

newDHPrivKey :: HasCallStack => MPI -> MPI -> MPI -> PrivKey
{-# INLINABLE newDHPrivKey  #-}
newDHPrivKey :: MPI -> MPI -> MPI -> PrivKey
newDHPrivKey MPI
p MPI
g MPI
x = do
    MPI -> (BotanStructT -> IO PrivKey) -> PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
p ((BotanStructT -> IO PrivKey) -> PrivKey)
-> (BotanStructT -> IO PrivKey) -> PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
p' -> MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
g ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
g' -> MPI -> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
x ((BotanStructT -> IO PrivKey) -> IO PrivKey)
-> (BotanStructT -> IO PrivKey) -> IO PrivKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
x' ->
        BotanStruct -> PrivKey
PrivKey (BotanStruct -> PrivKey) -> IO BotanStruct -> IO PrivKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (\ MBA# BotanStructT
key -> MBA# BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_privkey_load_dh MBA# BotanStructT
key BotanStructT
p' BotanStructT
g' BotanStructT
x') FunPtr (BotanStructT -> IO ())
botan_privkey_destroy

-- | Get Diffie-Hellman parameters
--
-- * Set p, g to group parameters
-- * Set y to the public key
--
getDHPubParams :: PubKey
               -> (MPI, MPI, MPI)   -- ^ (p, g, y)
{-# INLINABLE getDHPubParams  #-}
getDHPubParams :: PubKey -> (MPI, MPI, MPI)
getDHPubParams PubKey
key = (MPI
p, MPI
g, MPI
y)
  where
    !p :: MPI
p = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"p"
    !g :: MPI
g = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"g"
    !y :: MPI
y = PubKey -> CBytes -> MPI
pubKeyParam PubKey
key CBytes
"y"

newDHPubKey :: HasCallStack => MPI -> MPI -> MPI -> PubKey
{-# INLINABLE newDHPubKey  #-}
newDHPubKey :: MPI -> MPI -> MPI -> PubKey
newDHPubKey MPI
p MPI
g MPI
y = do
    MPI -> (BotanStructT -> IO PubKey) -> PubKey
forall a. MPI -> (BotanStructT -> IO a) -> a
unsafeWithMPI MPI
p ((BotanStructT -> IO PubKey) -> PubKey)
-> (BotanStructT -> IO PubKey) -> PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
p' ->
        MPI -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
g ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
g' ->
            MPI -> (BotanStructT -> IO PubKey) -> IO PubKey
forall a. MPI -> (BotanStructT -> IO a) -> IO a
withMPI MPI
y ((BotanStructT -> IO PubKey) -> IO PubKey)
-> (BotanStructT -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
y' ->
                BotanStruct -> PubKey
PubKey (BotanStruct -> PubKey) -> IO BotanStruct -> IO PubKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct (\ MBA# BotanStructT
pubKey -> MBA# BotanStructT
-> BotanStructT -> BotanStructT -> BotanStructT -> IO CInt
botan_pubkey_load_dh MBA# BotanStructT
pubKey BotanStructT
p' BotanStructT
g' BotanStructT
y') FunPtr (BotanStructT -> IO ())
botan_pubkey_destroy

----------------------------------------
-- Public Key Encryption / Decryption --
----------------------------------------

-- | Sets of allowed params for public key types.
--
-- The recommended values for eme is 'EME1_SHA1' or 'EME1_SHA256'.
-- If you need compatibility with protocols using the PKCS #1 v1.5 standard, you can also use 'EME_PKCS1_v1'5'.
--
-- To use SM2 encryption, use 'SM2EncParam'.
data EncParam
    = EME_RAW
    | EME_PKCS1_v1'5
    | EME_OAEP HashType CBytes              -- ^ hash, label
    | EME_OAEP' HashType HashType CBytes    -- ^ hash, mask gen hash, labal
    | SM2EncParam HashType

encParamToCBytes :: EncParam -> CBytes
{-# INLINABLE encParamToCBytes  #-}
encParamToCBytes :: EncParam -> CBytes
encParamToCBytes EncParam
EME_RAW              = CBytes
"Raw"
encParamToCBytes EncParam
EME_PKCS1_v1'5       = CBytes
"PKCS1v15"
encParamToCBytes (EME_OAEP  HashType
ht CBytes
label)
    | CBytes -> Bool
CB.null CBytes
label = [CBytes] -> CBytes
CB.concat [CBytes
"OAEP(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
",MGF1)" ]
    | Bool
otherwise = [CBytes] -> CBytes
CB.concat [CBytes
"OAEP(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
",MGF1,", CBytes
label, CBytes
")"]

encParamToCBytes (EME_OAEP' HashType
ht HashType
ht' CBytes
label)
    | CBytes -> Bool
CB.null CBytes
label =
        [CBytes] -> CBytes
CB.concat [CBytes
"OAEP(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
",MGF1(", HashType -> CBytes
hashTypeToCBytes HashType
ht', CBytes
"))"]
    | Bool
otherwise =
        [CBytes] -> CBytes
CB.concat [CBytes
"OAEP(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
",MGF1(", HashType -> CBytes
hashTypeToCBytes HashType
ht', CBytes
"),", CBytes
label, CBytes
")"]
encParamToCBytes (SM2EncParam HashType
ht) = HashType -> CBytes
hashTypeToCBytes HashType
ht

-- |  Encrypt a message, returning the ciphertext.
--
-- Though botan support DLIES and ECIES but only EME are exported via FFI, please use an algorithm that directly support eme encryption such as RSA and ElGamal.
--
pkEncrypt :: HasCallStack
          => PubKey -> EncParam -> RNG
          -> V.Bytes        -- ^ plaintext
          -> IO V.Bytes     -- ^ ciphertext
{-# INLINABLE pkEncrypt  #-}
pkEncrypt :: PubKey -> EncParam -> RNG -> Bytes -> IO Bytes
pkEncrypt PubKey
pubKey EncParam
padding RNG
rng Bytes
ptext = do
    BotanStruct
encryptor <-
        PubKey -> (BotanStructT -> IO BotanStruct) -> IO BotanStruct
forall r. PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey PubKey
pubKey ((BotanStructT -> IO BotanStruct) -> IO BotanStruct)
-> (BotanStructT -> IO BotanStruct) -> IO BotanStruct
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
pubKey' ->
        CBytes -> (BA# Word8 -> IO BotanStruct) -> IO BotanStruct
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe (EncParam -> CBytes
encParamToCBytes EncParam
padding) ((BA# Word8 -> IO BotanStruct) -> IO BotanStruct)
-> (BA# Word8 -> IO BotanStruct) -> IO BotanStruct
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
param' ->
            (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
                (\ MBA# BotanStructT
op -> MBA# BotanStructT -> BotanStructT -> BA# Word8 -> Word32 -> IO CInt
botan_pk_op_encrypt_create MBA# BotanStructT
op BotanStructT
pubKey' BA# Word8
param' Word32
0) -- Flags should be 0 in this version.
                FunPtr (BotanStructT -> IO ())
botan_pk_op_encrypt_destroy

    BotanStruct -> (BotanStructT -> IO Bytes) -> IO Bytes
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
encryptor ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op -> do
        let ptextLen :: CSize
ptextLen = Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
ptext)
        (CSize
len, ()
_) <- forall b.
Prim CSize =>
(MBA# BotanStructT -> IO b) -> IO (CSize, b)
forall a b. Prim a => (MBA# BotanStructT -> IO b) -> IO (a, b)
allocPrimUnsafe @CSize ((MBA# BotanStructT -> IO ()) -> IO (CSize, ()))
-> (MBA# BotanStructT -> IO ()) -> IO (CSize, ())
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
ret ->
            IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> CSize -> MBA# BotanStructT -> IO CInt
botan_pk_op_encrypt_output_length BotanStructT
op CSize
ptextLen MBA# BotanStructT
ret)
        RNG -> (BotanStructT -> IO Bytes) -> IO Bytes
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
rng' ->
            Bytes -> (BA# Word8 -> Int -> Int -> IO Bytes) -> IO Bytes
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
ptext ((BA# Word8 -> Int -> Int -> IO Bytes) -> IO Bytes)
-> (BA# Word8 -> Int -> Int -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
ptext' Int
ptextOff' Int
ptextLen' ->
            Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len) ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
out MBA# BotanStructT
len' ->
                BotanStructT
-> BotanStructT
-> MBA# BotanStructT
-> MBA# BotanStructT
-> BA# Word8
-> Int
-> Int
-> IO CInt
hs_botan_pk_op_encrypt BotanStructT
op BotanStructT
rng' MBA# BotanStructT
out MBA# BotanStructT
len' BA# Word8
ptext' Int
ptextOff' Int
ptextLen'

-- |  Decrypt a message, returning the plaintext.
--
-- Though botan support DLIES and ECIES but only EME are exported via FFI, please use an algorithm that directly support decryption such as 'RSA' and 'ElGamal'.
--
pkDecrypt :: HasCallStack => PrivKey -> EncParam
          -> V.Bytes            -- ^ ciphertext
          -> IO V.Bytes         -- ^ plaintext
{-# INLINABLE pkDecrypt  #-}
pkDecrypt :: PrivKey -> EncParam -> Bytes -> IO Bytes
pkDecrypt PrivKey
key EncParam
padding Bytes
ctext = do
    BotanStruct
decryptor <-
        PrivKey -> (BotanStructT -> IO BotanStruct) -> IO BotanStruct
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO BotanStruct) -> IO BotanStruct)
-> (BotanStructT -> IO BotanStruct) -> IO BotanStruct
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' ->
        CBytes -> (BA# Word8 -> IO BotanStruct) -> IO BotanStruct
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe (EncParam -> CBytes
encParamToCBytes EncParam
padding) ((BA# Word8 -> IO BotanStruct) -> IO BotanStruct)
-> (BA# Word8 -> IO BotanStruct) -> IO BotanStruct
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
param' ->
            (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
                (\ MBA# BotanStructT
op -> MBA# BotanStructT -> BotanStructT -> BA# Word8 -> Word32 -> IO CInt
botan_pk_op_decrypt_create MBA# BotanStructT
op BotanStructT
key' BA# Word8
param' Word32
0) -- Flags should be 0 in this version.
                FunPtr (BotanStructT -> IO ())
botan_pk_op_decrypt_destroy

    BotanStruct -> (BotanStructT -> IO Bytes) -> IO Bytes
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
decryptor ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op -> do
        let ctextLen :: CSize
ctextLen = Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> Int
forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
ctext)
        (CSize
len, ()
_) <- forall b.
Prim CSize =>
(MBA# BotanStructT -> IO b) -> IO (CSize, b)
forall a b. Prim a => (MBA# BotanStructT -> IO b) -> IO (a, b)
allocPrimUnsafe @CSize ((MBA# BotanStructT -> IO ()) -> IO (CSize, ()))
-> (MBA# BotanStructT -> IO ()) -> IO (CSize, ())
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
ret ->
            IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> CSize -> MBA# BotanStructT -> IO CInt
botan_pk_op_decrypt_output_length BotanStructT
op CSize
ctextLen MBA# BotanStructT
ret)
        Bytes -> (BA# Word8 -> Int -> Int -> IO Bytes) -> IO Bytes
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
ctext ((BA# Word8 -> Int -> Int -> IO Bytes) -> IO Bytes)
-> (BA# Word8 -> Int -> Int -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
ctext' Int
ctextOff' Int
ctextLen' ->
            Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len) ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ MBA# BotanStructT
out MBA# BotanStructT
len' ->
                BotanStructT
-> MBA# BotanStructT
-> MBA# BotanStructT
-> BA# Word8
-> Int
-> Int
-> IO CInt
hs_botan_pk_op_decrypt BotanStructT
op MBA# BotanStructT
out MBA# BotanStructT
len' BA# Word8
ctext' Int
ctextOff' Int
ctextLen'

--------------------------
-- Signature Generation --
--------------------------

-- | Signature params.
--
-- Currently available values for 'EMSA' include EMSA1, EMSA2, EMSA3, EMSA4, and Raw. All of them, except Raw, take a parameter naming a message digest function to hash the message with. The Raw encoding signs the input directly; if the message is too big, the signing operation will fail. Raw is not useful except in very specialized applications.
-- For RSA, use EMSA4 (also called PSS) unless you need compatibility with software that uses the older PKCS #1 v1.5 standard, in which case use EMSA3 (also called “EMSA-PKCS1-v1_5”). For DSA, ECDSA, ECKCDSA, ECGDSA and GOST 34.10-2001 you should use EMSA1.
--
data SignParam
    = EMSA1 HashType
    | EMSA2 HashType
    | EMSA3_RAW (Maybe HashType)
    | EMSA3 HashType
    | EMSA4_Raw HashType (Maybe Int)            -- ^ hash, salt size
    | EMSA4 HashType (Maybe Int)                -- ^ hash, salt size
    | ISO_9796_DS2 HashType Bool (Maybe Int)    -- ^ hash, implicit, salt size
    | ISO_9796_DS3 HashType Bool                -- ^ hash, implicit
    | EMSA_Raw
    | Ed25519Pure                               -- ^ pure Ed25519
    | Ed25519ph                                 -- ^ rfc8032 HashEdDSA variant
    | Ed25519Hash HashType                      -- ^ HashEdDSA
    | SM2SignParam CBytes HashType                  -- ^ userid, hash(GM/T 0009-2012 specifies
                                                -- @"1234567812345678"@ as the default userid)
    | XMSSEmptyParam                            -- ^ XMSS do not need param
  deriving (Int -> SignParam -> ShowS
[SignParam] -> ShowS
SignParam -> String
(Int -> SignParam -> ShowS)
-> (SignParam -> String)
-> ([SignParam] -> ShowS)
-> Show SignParam
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SignParam] -> ShowS
$cshowList :: [SignParam] -> ShowS
show :: SignParam -> String
$cshow :: SignParam -> String
showsPrec :: Int -> SignParam -> ShowS
$cshowsPrec :: Int -> SignParam -> ShowS
Show, ReadPrec [SignParam]
ReadPrec SignParam
Int -> ReadS SignParam
ReadS [SignParam]
(Int -> ReadS SignParam)
-> ReadS [SignParam]
-> ReadPrec SignParam
-> ReadPrec [SignParam]
-> Read SignParam
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SignParam]
$creadListPrec :: ReadPrec [SignParam]
readPrec :: ReadPrec SignParam
$creadPrec :: ReadPrec SignParam
readList :: ReadS [SignParam]
$creadList :: ReadS [SignParam]
readsPrec :: Int -> ReadS SignParam
$creadsPrec :: Int -> ReadS SignParam
Read, SignParam -> SignParam -> Bool
(SignParam -> SignParam -> Bool)
-> (SignParam -> SignParam -> Bool) -> Eq SignParam
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SignParam -> SignParam -> Bool
$c/= :: SignParam -> SignParam -> Bool
== :: SignParam -> SignParam -> Bool
$c== :: SignParam -> SignParam -> Bool
Eq, Eq SignParam
Eq SignParam
-> (SignParam -> SignParam -> Ordering)
-> (SignParam -> SignParam -> Bool)
-> (SignParam -> SignParam -> Bool)
-> (SignParam -> SignParam -> Bool)
-> (SignParam -> SignParam -> Bool)
-> (SignParam -> SignParam -> SignParam)
-> (SignParam -> SignParam -> SignParam)
-> Ord SignParam
SignParam -> SignParam -> Bool
SignParam -> SignParam -> Ordering
SignParam -> SignParam -> SignParam
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 :: SignParam -> SignParam -> SignParam
$cmin :: SignParam -> SignParam -> SignParam
max :: SignParam -> SignParam -> SignParam
$cmax :: SignParam -> SignParam -> SignParam
>= :: SignParam -> SignParam -> Bool
$c>= :: SignParam -> SignParam -> Bool
> :: SignParam -> SignParam -> Bool
$c> :: SignParam -> SignParam -> Bool
<= :: SignParam -> SignParam -> Bool
$c<= :: SignParam -> SignParam -> Bool
< :: SignParam -> SignParam -> Bool
$c< :: SignParam -> SignParam -> Bool
compare :: SignParam -> SignParam -> Ordering
$ccompare :: SignParam -> SignParam -> Ordering
$cp1Ord :: Eq SignParam
Ord, (forall x. SignParam -> Rep SignParam x)
-> (forall x. Rep SignParam x -> SignParam) -> Generic SignParam
forall x. Rep SignParam x -> SignParam
forall x. SignParam -> Rep SignParam x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep SignParam x -> SignParam
$cfrom :: forall x. SignParam -> Rep SignParam x
Generic)
  deriving anyclass (Int -> SignParam -> Builder ()
(Int -> SignParam -> Builder ()) -> Print SignParam
forall a. (Int -> a -> Builder ()) -> Print a
toUTF8BuilderP :: Int -> SignParam -> Builder ()
$ctoUTF8BuilderP :: Int -> SignParam -> Builder ()
T.Print, Value -> Converter SignParam
SignParam -> Value
SignParam -> Builder ()
(Value -> Converter SignParam)
-> (SignParam -> Value)
-> (SignParam -> Builder ())
-> JSON SignParam
forall a.
(Value -> Converter a)
-> (a -> Value) -> (a -> Builder ()) -> JSON a
encodeJSON :: SignParam -> Builder ()
$cencodeJSON :: SignParam -> Builder ()
toValue :: SignParam -> Value
$ctoValue :: SignParam -> Value
fromValue :: Value -> Converter SignParam
$cfromValue :: Value -> Converter SignParam
JSON)

emsaToCBytes :: SignParam -> CBytes
{-# INLINABLE emsaToCBytes  #-}
emsaToCBytes :: SignParam -> CBytes
emsaToCBytes (EMSA1 HashType
ht) = [CBytes] -> CBytes
CB.concat [CBytes
"EMSA1(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
")"]
emsaToCBytes (EMSA3_RAW (Just HashType
ht)) =
    [CBytes] -> CBytes
CB.concat [CBytes
"EMSA3(Raw,", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
")"]
emsaToCBytes (EMSA3_RAW Maybe HashType
_) = CBytes
"EMSA3(Raw)"
emsaToCBytes (EMSA3 HashType
ht) = [CBytes] -> CBytes
CB.concat [CBytes
"EMSA3(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
")"]
emsaToCBytes (EMSA4_Raw HashType
ht (Just Int
siz)) =
    [CBytes] -> CBytes
CB.concat [CBytes
"EMSA4_Raw(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
",MGF1,", Text -> CBytes
CB.fromText (Int -> Text
forall a. Print a => a -> Text
T.toText Int
siz) , CBytes
")"]
emsaToCBytes (EMSA4_Raw HashType
ht Maybe Int
_) =
    [CBytes] -> CBytes
CB.concat [CBytes
"EMSA4_Raw(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
")"]
emsaToCBytes (EMSA4 HashType
ht (Just Int
siz)) =
    [CBytes] -> CBytes
CB.concat [CBytes
"EMSA4(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
",MGF1,", Text -> CBytes
CB.fromText (Int -> Text
forall a. Print a => a -> Text
T.toText Int
siz) , CBytes
")"]
emsaToCBytes (EMSA4 HashType
ht Maybe Int
_) =
    [CBytes] -> CBytes
CB.concat [CBytes
"EMSA4(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
")"]
emsaToCBytes (ISO_9796_DS2 HashType
ht Bool
imp (Just Int
siz)) =
    [CBytes] -> CBytes
CB.concat [ CBytes
"ISO_9796_DS2(", HashType -> CBytes
hashTypeToCBytes HashType
ht
              , if Bool
imp then CBytes
",imp," else CBytes
",exp,"
              , Text -> CBytes
CB.fromText (Int -> Text
forall a. Print a => a -> Text
T.toText Int
siz) , CBytes
")"]
emsaToCBytes (ISO_9796_DS2 HashType
ht Bool
imp Maybe Int
_) =
    [CBytes] -> CBytes
CB.concat [ CBytes
"ISO_9796_DS2(", HashType -> CBytes
hashTypeToCBytes HashType
ht
              , if Bool
imp then CBytes
",imp)" else CBytes
",exp)"
              ]
emsaToCBytes (ISO_9796_DS3 HashType
ht Bool
imp) =
    [CBytes] -> CBytes
CB.concat [ CBytes
"ISO_9796_DS3(", HashType -> CBytes
hashTypeToCBytes HashType
ht
              , if Bool
imp then CBytes
",imp)" else CBytes
",exp)"
              ]
emsaToCBytes (EMSA2 HashType
ht) = [CBytes] -> CBytes
CB.concat [CBytes
"EMSA2(", HashType -> CBytes
hashTypeToCBytes HashType
ht, CBytes
")"]
emsaToCBytes SignParam
EMSA_Raw = CBytes
"Raw"
emsaToCBytes SignParam
Ed25519Pure = CBytes
"Pure"
emsaToCBytes SignParam
Ed25519ph = CBytes
"Ed25519ph"
emsaToCBytes (Ed25519Hash HashType
ht) = HashType -> CBytes
hashTypeToCBytes HashType
ht
emsaToCBytes (SM2SignParam CBytes
uid HashType
ht) = [CBytes] -> CBytes
CB.concat [CBytes
uid, CBytes
",", HashType -> CBytes
hashTypeToCBytes HashType
ht]
emsaToCBytes SignParam
_ = CBytes
""

-- The format defaults to IEEE_1363 which is the only available format for RSA. For DSA, ECDSA, ECGDSA and ECKCDSA you can also use DER_SEQUENCE, which will format the signature as an ASN.1 SEQUENCE value.
data SignFmt = DER_SEQUENCE | IEEE_1363
    deriving (SignFmt -> SignFmt -> Bool
(SignFmt -> SignFmt -> Bool)
-> (SignFmt -> SignFmt -> Bool) -> Eq SignFmt
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SignFmt -> SignFmt -> Bool
$c/= :: SignFmt -> SignFmt -> Bool
== :: SignFmt -> SignFmt -> Bool
$c== :: SignFmt -> SignFmt -> Bool
Eq, Eq SignFmt
Eq SignFmt
-> (SignFmt -> SignFmt -> Ordering)
-> (SignFmt -> SignFmt -> Bool)
-> (SignFmt -> SignFmt -> Bool)
-> (SignFmt -> SignFmt -> Bool)
-> (SignFmt -> SignFmt -> Bool)
-> (SignFmt -> SignFmt -> SignFmt)
-> (SignFmt -> SignFmt -> SignFmt)
-> Ord SignFmt
SignFmt -> SignFmt -> Bool
SignFmt -> SignFmt -> Ordering
SignFmt -> SignFmt -> SignFmt
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 :: SignFmt -> SignFmt -> SignFmt
$cmin :: SignFmt -> SignFmt -> SignFmt
max :: SignFmt -> SignFmt -> SignFmt
$cmax :: SignFmt -> SignFmt -> SignFmt
>= :: SignFmt -> SignFmt -> Bool
$c>= :: SignFmt -> SignFmt -> Bool
> :: SignFmt -> SignFmt -> Bool
$c> :: SignFmt -> SignFmt -> Bool
<= :: SignFmt -> SignFmt -> Bool
$c<= :: SignFmt -> SignFmt -> Bool
< :: SignFmt -> SignFmt -> Bool
$c< :: SignFmt -> SignFmt -> Bool
compare :: SignFmt -> SignFmt -> Ordering
$ccompare :: SignFmt -> SignFmt -> Ordering
$cp1Ord :: Eq SignFmt
Ord, Int -> SignFmt -> ShowS
[SignFmt] -> ShowS
SignFmt -> String
(Int -> SignFmt -> ShowS)
-> (SignFmt -> String) -> ([SignFmt] -> ShowS) -> Show SignFmt
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SignFmt] -> ShowS
$cshowList :: [SignFmt] -> ShowS
show :: SignFmt -> String
$cshow :: SignFmt -> String
showsPrec :: Int -> SignFmt -> ShowS
$cshowsPrec :: Int -> SignFmt -> ShowS
Show, Int -> SignFmt
SignFmt -> Int
SignFmt -> [SignFmt]
SignFmt -> SignFmt
SignFmt -> SignFmt -> [SignFmt]
SignFmt -> SignFmt -> SignFmt -> [SignFmt]
(SignFmt -> SignFmt)
-> (SignFmt -> SignFmt)
-> (Int -> SignFmt)
-> (SignFmt -> Int)
-> (SignFmt -> [SignFmt])
-> (SignFmt -> SignFmt -> [SignFmt])
-> (SignFmt -> SignFmt -> [SignFmt])
-> (SignFmt -> SignFmt -> SignFmt -> [SignFmt])
-> Enum SignFmt
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: SignFmt -> SignFmt -> SignFmt -> [SignFmt]
$cenumFromThenTo :: SignFmt -> SignFmt -> SignFmt -> [SignFmt]
enumFromTo :: SignFmt -> SignFmt -> [SignFmt]
$cenumFromTo :: SignFmt -> SignFmt -> [SignFmt]
enumFromThen :: SignFmt -> SignFmt -> [SignFmt]
$cenumFromThen :: SignFmt -> SignFmt -> [SignFmt]
enumFrom :: SignFmt -> [SignFmt]
$cenumFrom :: SignFmt -> [SignFmt]
fromEnum :: SignFmt -> Int
$cfromEnum :: SignFmt -> Int
toEnum :: Int -> SignFmt
$ctoEnum :: Int -> SignFmt
pred :: SignFmt -> SignFmt
$cpred :: SignFmt -> SignFmt
succ :: SignFmt -> SignFmt
$csucc :: SignFmt -> SignFmt
Enum, (forall x. SignFmt -> Rep SignFmt x)
-> (forall x. Rep SignFmt x -> SignFmt) -> Generic SignFmt
forall x. Rep SignFmt x -> SignFmt
forall x. SignFmt -> Rep SignFmt x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep SignFmt x -> SignFmt
$cfrom :: forall x. SignFmt -> Rep SignFmt x
Generic)
    deriving anyclass Int -> SignFmt -> Builder ()
(Int -> SignFmt -> Builder ()) -> Print SignFmt
forall a. (Int -> a -> Builder ()) -> Print a
toUTF8BuilderP :: Int -> SignFmt -> Builder ()
$ctoUTF8BuilderP :: Int -> SignFmt -> Builder ()
T.Print

signFmtToFlag :: SignFmt -> Word32
{-# INLINABLE signFmtToFlag  #-}
signFmtToFlag :: SignFmt -> Word32
signFmtToFlag SignFmt
DER_SEQUENCE = Word32
1
signFmtToFlag SignFmt
IEEE_1363    = Word32
0

data Signer = Signer
    { Signer -> BotanStruct
signerStruct :: {-# UNPACK #-} !BotanStruct
    , Signer -> Int
signerSize   :: {-# UNPACK #-} !Int           -- ^ output signature length
    }
    deriving (Int -> Signer -> ShowS
[Signer] -> ShowS
Signer -> String
(Int -> Signer -> ShowS)
-> (Signer -> String) -> ([Signer] -> ShowS) -> Show Signer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Signer] -> ShowS
$cshowList :: [Signer] -> ShowS
show :: Signer -> String
$cshow :: Signer -> String
showsPrec :: Int -> Signer -> ShowS
$cshowsPrec :: Int -> Signer -> ShowS
Show, (forall x. Signer -> Rep Signer x)
-> (forall x. Rep Signer x -> Signer) -> Generic Signer
forall x. Rep Signer x -> Signer
forall x. Signer -> Rep Signer x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Signer x -> Signer
$cfrom :: forall x. Signer -> Rep Signer x
Generic)
    deriving anyclass Int -> Signer -> Builder ()
(Int -> Signer -> Builder ()) -> Print Signer
forall a. (Int -> a -> Builder ()) -> Print a
toUTF8BuilderP :: Int -> Signer -> Builder ()
$ctoUTF8BuilderP :: Int -> Signer -> Builder ()
T.Print

newSigner :: HasCallStack => PrivKey -> SignParam -> SignFmt -> IO Signer
{-# INLINABLE newSigner  #-}
newSigner :: PrivKey -> SignParam -> SignFmt -> IO Signer
newSigner PrivKey
key SignParam
emsa SignFmt
fmt = do
    let name :: CBytes
name = SignParam -> CBytes
emsaToCBytes SignParam
emsa
    PrivKey -> (BotanStructT -> IO Signer) -> IO Signer
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO Signer) -> IO Signer)
-> (BotanStructT -> IO Signer) -> IO Signer
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' ->
        CBytes -> (BA# Word8 -> IO Signer) -> IO Signer
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
name ((BA# Word8 -> IO Signer) -> IO Signer)
-> (BA# Word8 -> IO Signer) -> IO Signer
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
arg -> do
            BotanStruct
op <- (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
                (\ MBA# BotanStructT
ret -> MBA# BotanStructT -> BotanStructT -> BA# Word8 -> Word32 -> IO CInt
botan_pk_op_sign_create MBA# BotanStructT
ret BotanStructT
key' BA# Word8
arg (SignFmt -> Word32
signFmtToFlag SignFmt
fmt))
                FunPtr (BotanStructT -> IO ())
botan_pk_op_sign_destroy
            CSize
siz <- BotanStruct -> (BotanStructT -> IO CSize) -> IO CSize
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
op ((BotanStructT -> IO CSize) -> IO CSize)
-> (BotanStructT -> IO CSize) -> IO CSize
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op' ->
                (CSize, ()) -> CSize
forall a b. (a, b) -> a
fst ((CSize, ()) -> CSize) -> IO (CSize, ()) -> IO CSize
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO ()) -> IO (CSize, ())
forall a b. Prim a => (MBA# BotanStructT -> IO b) -> IO (a, b)
allocPrimUnsafe @CSize (\ MBA# BotanStructT
siz' ->
                    IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanStructT -> MBA# BotanStructT -> IO CInt
botan_pk_op_sign_output_length BotanStructT
op' MBA# BotanStructT
siz')
            Signer -> IO Signer
forall (m :: * -> *) a. Monad m => a -> m a
return (BotanStruct -> Int -> Signer
Signer BotanStruct
op (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
siz))

updateSigner :: HasCallStack => Signer -> V.Bytes -> IO ()
{-# INLINABLE updateSigner  #-}
updateSigner :: Signer -> Bytes -> IO ()
updateSigner (Signer BotanStruct
op Int
_) Bytes
msg =
    BotanStruct -> (BotanStructT -> IO ()) -> IO ()
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
op ((BotanStructT -> IO ()) -> IO ())
-> (BotanStructT -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op' ->
    Bytes -> (BA# Word8 -> Int -> Int -> IO ()) -> IO ()
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
msg ((BA# Word8 -> Int -> Int -> IO ()) -> IO ())
-> (BA# Word8 -> Int -> Int -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
m Int
moff Int
mlen ->
        IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (BotanStructT -> BA# Word8 -> Int -> Int -> IO CInt
hs_botan_pk_op_sign_update BotanStructT
op' BA# Word8
m Int
moff Int
mlen)

-- | Produce a signature over all of the bytes passed to 'Signer'.
-- Afterwards, the sign operator is reset and may be used to sign a new message.
finalSigner :: HasCallStack => Signer -> RNG -> IO V.Bytes
{-# INLINABLE finalSigner  #-}
finalSigner :: Signer -> RNG -> IO Bytes
finalSigner (Signer BotanStruct
op Int
siz) RNG
rng =
    BotanStruct -> (BotanStructT -> IO Bytes) -> IO Bytes
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
op ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op' ->
    RNG -> (BotanStructT -> IO Bytes) -> IO Bytes
forall a. RNG -> (BotanStructT -> IO a) -> IO a
withRNG RNG
rng ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
rng' ->
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe Int
siz ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ BotanStructT
-> BotanStructT
-> MBA# BotanStructT
-> MBA# BotanStructT
-> IO CInt
botan_pk_op_sign_finish BotanStructT
op' BotanStructT
rng'

-- | Trun 'Signer' to a 'V.Bytes' sink, update 'Signer' by write bytes to the sink.
--
sinkToSigner :: HasCallStack => HasCallStack => Signer -> Sink V.Bytes
{-# INLINABLE sinkToSigner #-}
sinkToSigner :: Signer -> Sink Bytes
sinkToSigner Signer
h = \ Maybe Void -> IO ()
k Maybe Bytes
mbs -> case Maybe Bytes
mbs of
    Just Bytes
bs -> HasCallStack => Signer -> Bytes -> IO ()
Signer -> Bytes -> IO ()
updateSigner Signer
h Bytes
bs
    Maybe Bytes
_       -> Maybe Void -> IO ()
k Maybe Void
forall a. Maybe a
EOF

-- | Directly sign a message, with system RNG.
sign :: HasCallStack
     => PrivKey -> SignParam -> SignFmt
     -> V.Bytes         -- ^ input
     -> IO V.Bytes      -- ^ signature
{-# INLINABLE sign #-}
sign :: PrivKey -> SignParam -> SignFmt -> Bytes -> IO Bytes
sign PrivKey
key SignParam
emsa SignFmt
fmt Bytes
inp = do
    Signer
m <- HasCallStack => PrivKey -> SignParam -> SignFmt -> IO Signer
PrivKey -> SignParam -> SignFmt -> IO Signer
newSigner PrivKey
key SignParam
emsa SignFmt
fmt
    HasCallStack => Signer -> Bytes -> IO ()
Signer -> Bytes -> IO ()
updateSigner Signer
m Bytes
inp
    HasCallStack => Signer -> RNG -> IO Bytes
Signer -> RNG -> IO Bytes
finalSigner Signer
m (RNG -> IO Bytes) -> IO RNG -> IO Bytes
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO RNG
HasCallStack => IO RNG
getRNG

-- | Directly compute a chunked message's mac with system RNG.
signChunks :: HasCallStack
           => PrivKey -> SignParam -> SignFmt
           -> [V.Bytes]
           -> IO V.Bytes
{-# INLINABLE signChunks #-}
signChunks :: PrivKey -> SignParam -> SignFmt -> [Bytes] -> IO Bytes
signChunks PrivKey
key SignParam
emsa SignFmt
fmt [Bytes]
inps = do
    Signer
m <- HasCallStack => PrivKey -> SignParam -> SignFmt -> IO Signer
PrivKey -> SignParam -> SignFmt -> IO Signer
newSigner PrivKey
key SignParam
emsa SignFmt
fmt
    (Bytes -> IO ()) -> [Bytes] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (HasCallStack => Signer -> Bytes -> IO ()
Signer -> Bytes -> IO ()
updateSigner Signer
m) [Bytes]
inps
    HasCallStack => Signer -> RNG -> IO Bytes
Signer -> RNG -> IO Bytes
finalSigner Signer
m (RNG -> IO Bytes) -> IO RNG -> IO Bytes
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO RNG
HasCallStack => IO RNG
getRNG

----------------------------
-- Signature Verification --
----------------------------

newtype Verifier = Verifier BotanStruct
    deriving (Int -> Verifier -> ShowS
[Verifier] -> ShowS
Verifier -> String
(Int -> Verifier -> ShowS)
-> (Verifier -> String) -> ([Verifier] -> ShowS) -> Show Verifier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Verifier] -> ShowS
$cshowList :: [Verifier] -> ShowS
show :: Verifier -> String
$cshow :: Verifier -> String
showsPrec :: Int -> Verifier -> ShowS
$cshowsPrec :: Int -> Verifier -> ShowS
Show, (forall x. Verifier -> Rep Verifier x)
-> (forall x. Rep Verifier x -> Verifier) -> Generic Verifier
forall x. Rep Verifier x -> Verifier
forall x. Verifier -> Rep Verifier x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Verifier x -> Verifier
$cfrom :: forall x. Verifier -> Rep Verifier x
Generic)
    deriving anyclass Int -> Verifier -> Builder ()
(Int -> Verifier -> Builder ()) -> Print Verifier
forall a. (Int -> a -> Builder ()) -> Print a
toUTF8BuilderP :: Int -> Verifier -> Builder ()
$ctoUTF8BuilderP :: Int -> Verifier -> Builder ()
T.Print

newVerifier :: HasCallStack => PubKey -> SignParam -> SignFmt -> IO Verifier
{-# INLINABLE newVerifier  #-}
newVerifier :: PubKey -> SignParam -> SignFmt -> IO Verifier
newVerifier PubKey
pubKey SignParam
emsa SignFmt
fmt = do
    let param :: CBytes
param = SignParam -> CBytes
emsaToCBytes SignParam
emsa
    PubKey -> (BotanStructT -> IO Verifier) -> IO Verifier
forall r. PubKey -> (BotanStructT -> IO r) -> IO r
withPubKey PubKey
pubKey ((BotanStructT -> IO Verifier) -> IO Verifier)
-> (BotanStructT -> IO Verifier) -> IO Verifier
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
pubKey' ->
        CBytes -> (BA# Word8 -> IO Verifier) -> IO Verifier
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe CBytes
param ((BA# Word8 -> IO Verifier) -> IO Verifier)
-> (BA# Word8 -> IO Verifier) -> IO Verifier
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
arg -> do
            BotanStruct
op <- (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
                (\ MBA# BotanStructT
ret -> MBA# BotanStructT -> BotanStructT -> BA# Word8 -> Word32 -> IO CInt
botan_pk_op_verify_create MBA# BotanStructT
ret BotanStructT
pubKey' BA# Word8
arg (SignFmt -> Word32
signFmtToFlag SignFmt
fmt))
                FunPtr (BotanStructT -> IO ())
botan_pk_op_verify_destroy
            Verifier -> IO Verifier
forall (m :: * -> *) a. Monad m => a -> m a
return (BotanStruct -> Verifier
Verifier BotanStruct
op)

updateVerifier :: HasCallStack => Verifier -> V.Bytes -> IO ()
{-# INLINABLE updateVerifier  #-}
updateVerifier :: Verifier -> Bytes -> IO ()
updateVerifier (Verifier BotanStruct
op) Bytes
msg = do
    BotanStruct -> (BotanStructT -> IO ()) -> IO ()
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
op ((BotanStructT -> IO ()) -> IO ())
-> (BotanStructT -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op' ->
        Bytes -> (BA# Word8 -> Int -> Int -> IO ()) -> IO ()
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
msg ((BA# Word8 -> Int -> Int -> IO ()) -> IO ())
-> (BA# Word8 -> Int -> Int -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
msg' Int
off Int
len ->
            IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanStructT -> BA# Word8 -> Int -> Int -> IO CInt
hs_botan_pk_op_verify_update BotanStructT
op' BA# Word8
msg' Int
off Int
len

finalVerifier :: HasCallStack => Verifier -> V.Bytes -> IO Bool
{-# INLINABLE finalVerifier  #-}
finalVerifier :: Verifier -> Bytes -> IO Bool
finalVerifier (Verifier BotanStruct
op) Bytes
msg =
    BotanStruct -> (BotanStructT -> IO Bool) -> IO Bool
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
op ((BotanStructT -> IO Bool) -> IO Bool)
-> (BotanStructT -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op' ->
    Bytes -> (BA# Word8 -> Int -> Int -> IO Bool) -> IO Bool
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
msg ((BA# Word8 -> Int -> Int -> IO Bool) -> IO Bool)
-> (BA# Word8 -> Int -> Int -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
msg' Int
off Int
len -> do
        CInt
r <- IO CInt -> IO CInt
forall a. (HasCallStack, Integral a) => IO a -> IO a
throwBotanIfMinus (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ BotanStructT -> BA# Word8 -> Int -> Int -> IO CInt
hs_botan_pk_op_verify_finish BotanStructT
op' BA# Word8
msg' Int
off Int
len
        Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
BOTAN_FFI_SUCCESS
--    BOTAN_FFI_SUCCESS = 0,
--    BOTAN_FFI_INVALID_VERIFIER = 1

-- | Trun 'Verifier' to a 'V.Bytes' sink, update 'Verifier' by write bytes to the sink.
--
sinkToVerifier :: HasCallStack => Verifier -> Sink V.Bytes
{-# INLINABLE sinkToVerifier  #-}
sinkToVerifier :: Verifier -> Sink Bytes
sinkToVerifier Verifier
h = \ Maybe Void -> IO ()
k Maybe Bytes
mbs -> case Maybe Bytes
mbs of
    Just Bytes
bs -> HasCallStack => Verifier -> Bytes -> IO ()
Verifier -> Bytes -> IO ()
updateVerifier Verifier
h Bytes
bs
    Maybe Bytes
_       -> Maybe Void -> IO ()
k Maybe Void
forall a. Maybe a
EOF

-- | Directly sign a message.
verify :: HasCallStack
       => PubKey -> SignParam -> SignFmt
       -> V.Bytes  -- ^ input
       -> V.Bytes  -- ^ signature
       -> IO Bool
{-# INLINABLE verify #-}
verify :: PubKey -> SignParam -> SignFmt -> Bytes -> Bytes -> IO Bool
verify PubKey
key SignParam
emsa SignFmt
fmt Bytes
inp Bytes
sig = do
    Verifier
m <- HasCallStack => PubKey -> SignParam -> SignFmt -> IO Verifier
PubKey -> SignParam -> SignFmt -> IO Verifier
newVerifier PubKey
key SignParam
emsa SignFmt
fmt
    HasCallStack => Verifier -> Bytes -> IO ()
Verifier -> Bytes -> IO ()
updateVerifier Verifier
m Bytes
inp
    HasCallStack => Verifier -> Bytes -> IO Bool
Verifier -> Bytes -> IO Bool
finalVerifier Verifier
m Bytes
sig

-- | Directly compute a chunked message's mac.
verifyChunks :: HasCallStack
           => PubKey -> SignParam -> SignFmt
           -> [V.Bytes]
           -> V.Bytes           -- ^ signature
           -> IO Bool
{-# INLINABLE verifyChunks  #-}
verifyChunks :: PubKey -> SignParam -> SignFmt -> [Bytes] -> Bytes -> IO Bool
verifyChunks PubKey
key SignParam
emsa SignFmt
fmt [Bytes]
inps Bytes
sig = do
    Verifier
m <- HasCallStack => PubKey -> SignParam -> SignFmt -> IO Verifier
PubKey -> SignParam -> SignFmt -> IO Verifier
newVerifier PubKey
key SignParam
emsa SignFmt
fmt
    (Bytes -> IO ()) -> [Bytes] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (HasCallStack => Verifier -> Bytes -> IO ()
Verifier -> Bytes -> IO ()
updateVerifier Verifier
m) [Bytes]
inps
    HasCallStack => Verifier -> Bytes -> IO Bool
Verifier -> Bytes -> IO Bool
finalVerifier Verifier
m Bytes
sig

-------------------
-- Key Agreement --
-------------------

-- | Key agreement object.
data KeyAgreement = KeyAgreement
    { KeyAgreement -> BotanStruct
keyAgreementStruct :: {-# UNPACK #-} !BotanStruct
    , KeyAgreement -> Int
keyAgreementSize   :: {-# UNPACK #-} !Int     -- ^ size of the agreed key
    }
    deriving (Int -> KeyAgreement -> ShowS
[KeyAgreement] -> ShowS
KeyAgreement -> String
(Int -> KeyAgreement -> ShowS)
-> (KeyAgreement -> String)
-> ([KeyAgreement] -> ShowS)
-> Show KeyAgreement
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [KeyAgreement] -> ShowS
$cshowList :: [KeyAgreement] -> ShowS
show :: KeyAgreement -> String
$cshow :: KeyAgreement -> String
showsPrec :: Int -> KeyAgreement -> ShowS
$cshowsPrec :: Int -> KeyAgreement -> ShowS
Show, (forall x. KeyAgreement -> Rep KeyAgreement x)
-> (forall x. Rep KeyAgreement x -> KeyAgreement)
-> Generic KeyAgreement
forall x. Rep KeyAgreement x -> KeyAgreement
forall x. KeyAgreement -> Rep KeyAgreement x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep KeyAgreement x -> KeyAgreement
$cfrom :: forall x. KeyAgreement -> Rep KeyAgreement x
Generic)
    deriving anyclass Int -> KeyAgreement -> Builder ()
(Int -> KeyAgreement -> Builder ()) -> Print KeyAgreement
forall a. (Int -> a -> Builder ()) -> Print a
toUTF8BuilderP :: Int -> KeyAgreement -> Builder ()
$ctoUTF8BuilderP :: Int -> KeyAgreement -> Builder ()
T.Print

-- | Create a new key agreement operation with a given key pair and KDF algorithm.
--
-- Please use a key type that support key agreement, such as 'DH', 'ECDH', or 'Curve25519'.
--
newKeyAgreement :: HasCallStack => PrivKey -> KDFType -> IO KeyAgreement
{-# INLINABLE newKeyAgreement  #-}
newKeyAgreement :: PrivKey -> KDFType -> IO KeyAgreement
newKeyAgreement PrivKey
key KDFType
kdf =
    PrivKey -> (BotanStructT -> IO KeyAgreement) -> IO KeyAgreement
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO KeyAgreement) -> IO KeyAgreement)
-> (BotanStructT -> IO KeyAgreement) -> IO KeyAgreement
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' ->
    CBytes -> (BA# Word8 -> IO KeyAgreement) -> IO KeyAgreement
forall a. CBytes -> (BA# Word8 -> IO a) -> IO a
CB.withCBytesUnsafe (KDFType -> CBytes
kdfTypeToCBytes KDFType
kdf) ((BA# Word8 -> IO KeyAgreement) -> IO KeyAgreement)
-> (BA# Word8 -> IO KeyAgreement) -> IO KeyAgreement
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
kdf' -> do
        BotanStruct
op <- (MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO ()) -> IO BotanStruct
forall a.
HasCallStack =>
(MBA# BotanStructT -> IO CInt)
-> FunPtr (BotanStructT -> IO a) -> IO BotanStruct
newBotanStruct
            (\ MBA# BotanStructT
op -> MBA# BotanStructT -> BotanStructT -> BA# Word8 -> Word32 -> IO CInt
botan_pk_op_key_agreement_create MBA# BotanStructT
op BotanStructT
key' BA# Word8
kdf' Word32
0) -- Flags should be 0 in this version.
            FunPtr (BotanStructT -> IO ())
botan_pk_op_key_agreement_destroy
        CSize
siz <- BotanStruct -> (BotanStructT -> IO CSize) -> IO CSize
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
op ((BotanStructT -> IO CSize) -> IO CSize)
-> (BotanStructT -> IO CSize) -> IO CSize
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op' ->
            (CSize, ()) -> CSize
forall a b. (a, b) -> a
fst ((CSize, ()) -> CSize) -> IO (CSize, ()) -> IO CSize
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MBA# BotanStructT -> IO ()) -> IO (CSize, ())
forall a b. Prim a => (MBA# BotanStructT -> IO b) -> IO (a, b)
allocPrimUnsafe @CSize (\ MBA# BotanStructT
siz' ->
                IO CInt -> IO ()
forall a. (HasCallStack, Integral a) => IO a -> IO ()
throwBotanIfMinus_ (IO CInt -> IO ()) -> IO CInt -> IO ()
forall a b. (a -> b) -> a -> b
$ BotanStructT -> MBA# BotanStructT -> IO CInt
botan_pk_op_key_agreement_size BotanStructT
op' MBA# BotanStructT
siz')
        KeyAgreement -> IO KeyAgreement
forall (m :: * -> *) a. Monad m => a -> m a
return (BotanStruct -> Int -> KeyAgreement
KeyAgreement BotanStruct
op (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
siz))

-- | Produce the public value to send to other party.
--
exportKeyAgreementPublic :: HasCallStack => PrivKey -> IO V.Bytes
{-# INLINABLE exportKeyAgreementPublic  #-}
exportKeyAgreementPublic :: PrivKey -> IO Bytes
exportKeyAgreementPublic PrivKey
key =
    PrivKey -> (BotanStructT -> IO Bytes) -> IO Bytes
forall r. HasCallStack => PrivKey -> (BotanStructT -> IO r) -> IO r
withPrivKey PrivKey
key ((BotanStructT -> IO Bytes) -> IO Bytes)
-> (BotanStructT -> IO Bytes) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
key' ->
    Int
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall r.
(HasCallStack, Integral r) =>
Int -> (MBA# BotanStructT -> MBA# BotanStructT -> IO r) -> IO Bytes
allocBotanBufferUnsafe Int
128 ((MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes)
-> (MBA# BotanStructT -> MBA# BotanStructT -> IO CInt) -> IO Bytes
forall a b. (a -> b) -> a -> b
$ BotanStructT -> MBA# BotanStructT -> MBA# BotanStructT -> IO CInt
botan_pk_op_key_agreement_export_public BotanStructT
key'

-- | How key agreement works is that you trade public values with some other party, and then each of you runs a computation with the other’s value and your key (this should return the same result to both parties).
keyAgree ::
    HasCallStack =>
    KeyAgreement ->
    -- | other key's public
    V.Bytes ->
    -- | salt
    V.Bytes ->
    IO Secret
{-# INLINABLE keyAgree  #-}
keyAgree :: KeyAgreement -> Bytes -> Bytes -> IO Secret
keyAgree (KeyAgreement BotanStruct
op Int
siz) Bytes
others Bytes
salt =
    BotanStruct -> (BotanStructT -> IO Secret) -> IO Secret
forall a. BotanStruct -> (BotanStructT -> IO a) -> IO a
withBotanStruct BotanStruct
op ((BotanStructT -> IO Secret) -> IO Secret)
-> (BotanStructT -> IO Secret) -> IO Secret
forall a b. (a -> b) -> a -> b
$ \ BotanStructT
op' ->
    Bytes -> (BA# Word8 -> Int -> Int -> IO Secret) -> IO Secret
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
others ((BA# Word8 -> Int -> Int -> IO Secret) -> IO Secret)
-> (BA# Word8 -> Int -> Int -> IO Secret) -> IO Secret
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
others' Int
others_off Int
others_len ->
    Bytes -> (BA# Word8 -> Int -> Int -> IO Secret) -> IO Secret
forall a b.
Prim a =>
PrimVector a -> (BA# Word8 -> Int -> Int -> IO b) -> IO b
withPrimVectorUnsafe Bytes
salt ((BA# Word8 -> Int -> Int -> IO Secret) -> IO Secret)
-> (BA# Word8 -> Int -> Int -> IO Secret) -> IO Secret
forall a b. (a -> b) -> a -> b
$ \ BA# Word8
salt' Int
salt_off Int
salt_len ->
    Int -> (Ptr Word8 -> IO CInt) -> IO Secret
forall r. Int -> (Ptr Word8 -> IO r) -> IO Secret
newSecret Int
siz ((Ptr Word8 -> IO CInt) -> IO Secret)
-> (Ptr Word8 -> IO CInt) -> IO Secret
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
ret ->
        BotanStructT
-> Ptr Word8
-> CSize
-> BA# Word8
-> Int
-> Int
-> BA# Word8
-> Int
-> Int
-> IO CInt
hs_botan_pk_op_key_agreement BotanStructT
op' Ptr Word8
ret (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
siz) BA# Word8
others'
            Int
others_off Int
others_len BA# Word8
salt' Int
salt_off Int
salt_len