    -- |
    -- Module      : Network.TLS.Crypto.IES
    -- License     : BSD-style
    -- Maintainer  : Kazu Yamamoto <kazu@iij.ad.jp>
    -- Stability   : experimental
    -- Portability : unknown
    --
    module Network.TLS.Crypto.IES
        (
          GroupPublic
        , GroupPrivate
        , GroupKey
        -- * Group methods
        , groupGenerateKeyPair
        , groupGetPubShared
        , groupGetShared
        , encodeGroupPublic
        , decodeGroupPublic
        -- * Compatibility with 'Network.TLS.Crypto.DH'
        , dhParamsForGroup
        , dhGroupGenerateKeyPair
        , dhGroupGetPubShared
        ) where

    import Control.Arrow
    import Crypto.ECC
    import Crypto.Error
    import Crypto.Number.Generate
    import Crypto.PubKey.DH hiding (generateParams)
    import Crypto.PubKey.ECIES
    import qualified Data.ByteArray as B
    import Data.Proxy
    import Network.TLS.Crypto.Types
    import Network.TLS.Extra.FFDHE
    import Network.TLS.Imports
    import Network.TLS.RNG
    import Network.TLS.Util.Serialization (os2ip,i2ospOf_)

    data GroupPrivate = GroupPri_P256 (Scalar Curve_P256R1)
                      | GroupPri_P384 (Scalar Curve_P384R1)
                      | GroupPri_P521 (Scalar Curve_P521R1)
                      | GroupPri_X255 (Scalar Curve_X25519)
                      | GroupPri_X448 (Scalar Curve_X448)
                      | GroupPri_FFDHE2048 PrivateNumber
                      | GroupPri_FFDHE3072 PrivateNumber
                      | GroupPri_FFDHE4096 PrivateNumber
                      | GroupPri_FFDHE6144 PrivateNumber
                      | GroupPri_FFDHE8192 PrivateNumber
                      deriving (GroupPrivate -> GroupPrivate -> Bool
    (GroupPrivate -> GroupPrivate -> Bool)
    -> (GroupPrivate -> GroupPrivate -> Bool) -> Eq GroupPrivate
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: GroupPrivate -> GroupPrivate -> Bool
    == :: GroupPrivate -> GroupPrivate -> Bool
    $c/= :: GroupPrivate -> GroupPrivate -> Bool
    /= :: GroupPrivate -> GroupPrivate -> Bool
    Eq, Int -> GroupPrivate -> ShowS
    [GroupPrivate] -> ShowS
    GroupPrivate -> String
    (Int -> GroupPrivate -> ShowS)
    -> (GroupPrivate -> String)
    -> ([GroupPrivate] -> ShowS)
    -> Show GroupPrivate
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> GroupPrivate -> ShowS
    showsPrec :: Int -> GroupPrivate -> ShowS
    $cshow :: GroupPrivate -> String
    show :: GroupPrivate -> String
    $cshowList :: [GroupPrivate] -> ShowS
    showList :: [GroupPrivate] -> ShowS
    Show)

    data GroupPublic = GroupPub_P256 (Point Curve_P256R1)
                     | GroupPub_P384 (Point Curve_P384R1)
                     | GroupPub_P521 (Point Curve_P521R1)
                     | GroupPub_X255 (Point Curve_X25519)
                     | GroupPub_X448 (Point Curve_X448)
                     | GroupPub_FFDHE2048 PublicNumber
                     | GroupPub_FFDHE3072 PublicNumber
                     | GroupPub_FFDHE4096 PublicNumber
                     | GroupPub_FFDHE6144 PublicNumber
                     | GroupPub_FFDHE8192 PublicNumber
                     deriving (GroupPublic -> GroupPublic -> Bool
    (GroupPublic -> GroupPublic -> Bool)
    -> (GroupPublic -> GroupPublic -> Bool) -> Eq GroupPublic
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: GroupPublic -> GroupPublic -> Bool
    == :: GroupPublic -> GroupPublic -> Bool
    $c/= :: GroupPublic -> GroupPublic -> Bool
    /= :: GroupPublic -> GroupPublic -> Bool
    Eq, Int -> GroupPublic -> ShowS
    [GroupPublic] -> ShowS
    GroupPublic -> String
    (Int -> GroupPublic -> ShowS)
    -> (GroupPublic -> String)
    -> ([GroupPublic] -> ShowS)
    -> Show GroupPublic
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> GroupPublic -> ShowS
    showsPrec :: Int -> GroupPublic -> ShowS
    $cshow :: GroupPublic -> String
    show :: GroupPublic -> String
    $cshowList :: [GroupPublic] -> ShowS
    showList :: [GroupPublic] -> ShowS
    Show)

    type GroupKey = SharedSecret

    p256 :: Proxy Curve_P256R1
    p256 :: Proxy Curve_P256R1
    p256 = Proxy Curve_P256R1
    forall {k} (t :: k). Proxy t
    Proxy

    p384 :: Proxy Curve_P384R1
    p384 :: Proxy Curve_P384R1
    p384 = Proxy Curve_P384R1
    forall {k} (t :: k). Proxy t
    Proxy

    p521 :: Proxy Curve_P521R1
    p521 :: Proxy Curve_P521R1
    p521 = Proxy Curve_P521R1
    forall {k} (t :: k). Proxy t
    Proxy

    x25519 :: Proxy Curve_X25519
    x25519 :: Proxy Curve_X25519
    x25519 = Proxy Curve_X25519
    forall {k} (t :: k). Proxy t
    Proxy

    x448 :: Proxy Curve_X448
    x448 :: Proxy Curve_X448
    x448 = Proxy Curve_X448
    forall {k} (t :: k). Proxy t
    Proxy

    dhParamsForGroup :: Group -> Maybe Params
    dhParamsForGroup :: Group -> Maybe Params
    dhParamsForGroup Group
    FFDHE2048 = Params -> Maybe Params
    forall a. a -> Maybe a
    Just Params
    ffdhe2048
    dhParamsForGroup Group
    FFDHE3072 = Params -> Maybe Params
    forall a. a -> Maybe a
    Just Params
    ffdhe3072
    dhParamsForGroup Group
    FFDHE4096 = Params -> Maybe Params
    forall a. a -> Maybe a
    Just Params
    ffdhe4096
    dhParamsForGroup Group
    FFDHE6144 = Params -> Maybe Params
    forall a. a -> Maybe a
    Just Params
    ffdhe6144
    dhParamsForGroup Group
    FFDHE8192 = Params -> Maybe Params
    forall a. a -> Maybe a
    Just Params
    ffdhe8192
    dhParamsForGroup Group
    _         = Maybe Params
    forall a. Maybe a
    Nothing

    groupGenerateKeyPair :: MonadRandom r => Group -> r (GroupPrivate, GroupPublic)
    groupGenerateKeyPair :: forall (r :: * -> *).
    MonadRandom r =>
    Group -> r (GroupPrivate, GroupPublic)
    groupGenerateKeyPair Group
    P256   =
        (Scalar Curve_P256R1 -> GroupPrivate
    GroupPri_P256,Point Curve_P256R1 -> GroupPublic
    GroupPub_P256) (Scalar Curve_P256R1 -> GroupPrivate,
     Point Curve_P256R1 -> GroupPublic)
    -> r (KeyPair Curve_P256R1) -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *) a.
    MonadRandom r =>
    (Scalar a -> GroupPrivate, Point a -> GroupPublic)
    -> r (KeyPair a) -> r (GroupPrivate, GroupPublic)
    `fs` Proxy Curve_P256R1 -> r (KeyPair Curve_P256R1)
    forall curve (randomly :: * -> *) (proxy :: * -> *).
    (EllipticCurve curve, MonadRandom randomly) =>
    proxy curve -> randomly (KeyPair curve)
    forall (randomly :: * -> *) (proxy :: * -> *).
    MonadRandom randomly =>
    proxy Curve_P256R1 -> randomly (KeyPair Curve_P256R1)
    curveGenerateKeyPair Proxy Curve_P256R1
    p256
    groupGenerateKeyPair Group
    P384   =
        (Scalar Curve_P384R1 -> GroupPrivate
    GroupPri_P384,Point Curve_P384R1 -> GroupPublic
    GroupPub_P384) (Scalar Curve_P384R1 -> GroupPrivate,
     Point Curve_P384R1 -> GroupPublic)
    -> r (KeyPair Curve_P384R1) -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *) a.
    MonadRandom r =>
    (Scalar a -> GroupPrivate, Point a -> GroupPublic)
    -> r (KeyPair a) -> r (GroupPrivate, GroupPublic)
    `fs` Proxy Curve_P384R1 -> r (KeyPair Curve_P384R1)
    forall curve (randomly :: * -> *) (proxy :: * -> *).
    (EllipticCurve curve, MonadRandom randomly) =>
    proxy curve -> randomly (KeyPair curve)
    forall (randomly :: * -> *) (proxy :: * -> *).
    MonadRandom randomly =>
    proxy Curve_P384R1 -> randomly (KeyPair Curve_P384R1)
    curveGenerateKeyPair Proxy Curve_P384R1
    p384
    groupGenerateKeyPair Group
    P521   =
        (Scalar Curve_P521R1 -> GroupPrivate
    GroupPri_P521,Point Curve_P521R1 -> GroupPublic
    GroupPub_P521) (Scalar Curve_P521R1 -> GroupPrivate,
     Point Curve_P521R1 -> GroupPublic)
    -> r (KeyPair Curve_P521R1) -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *) a.
    MonadRandom r =>
    (Scalar a -> GroupPrivate, Point a -> GroupPublic)
    -> r (KeyPair a) -> r (GroupPrivate, GroupPublic)
    `fs` Proxy Curve_P521R1 -> r (KeyPair Curve_P521R1)
    forall curve (randomly :: * -> *) (proxy :: * -> *).
    (EllipticCurve curve, MonadRandom randomly) =>
    proxy curve -> randomly (KeyPair curve)
    forall (randomly :: * -> *) (proxy :: * -> *).
    MonadRandom randomly =>
    proxy Curve_P521R1 -> randomly (KeyPair Curve_P521R1)
    curveGenerateKeyPair Proxy Curve_P521R1
    p521
    groupGenerateKeyPair Group
    X25519 =
        (Scalar Curve_X25519 -> GroupPrivate
    GroupPri_X255,Point Curve_X25519 -> GroupPublic
    GroupPub_X255) (Scalar Curve_X25519 -> GroupPrivate,
     Point Curve_X25519 -> GroupPublic)
    -> r (KeyPair Curve_X25519) -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *) a.
    MonadRandom r =>
    (Scalar a -> GroupPrivate, Point a -> GroupPublic)
    -> r (KeyPair a) -> r (GroupPrivate, GroupPublic)
    `fs` Proxy Curve_X25519 -> r (KeyPair Curve_X25519)
    forall curve (randomly :: * -> *) (proxy :: * -> *).
    (EllipticCurve curve, MonadRandom randomly) =>
    proxy curve -> randomly (KeyPair curve)
    forall (randomly :: * -> *) (proxy :: * -> *).
    MonadRandom randomly =>
    proxy Curve_X25519 -> randomly (KeyPair Curve_X25519)
    curveGenerateKeyPair Proxy Curve_X25519
    x25519
    groupGenerateKeyPair Group
    X448 =
        (Scalar Curve_X448 -> GroupPrivate
    GroupPri_X448,Point Curve_X448 -> GroupPublic
    GroupPub_X448) (Scalar Curve_X448 -> GroupPrivate,
     Point Curve_X448 -> GroupPublic)
    -> r (KeyPair Curve_X448) -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *) a.
    MonadRandom r =>
    (Scalar a -> GroupPrivate, Point a -> GroupPublic)
    -> r (KeyPair a) -> r (GroupPrivate, GroupPublic)
    `fs` Proxy Curve_X448 -> r (KeyPair Curve_X448)
    forall curve (randomly :: * -> *) (proxy :: * -> *).
    (EllipticCurve curve, MonadRandom randomly) =>
    proxy curve -> randomly (KeyPair curve)
    forall (randomly :: * -> *) (proxy :: * -> *).
    MonadRandom randomly =>
    proxy Curve_X448 -> randomly (KeyPair Curve_X448)
    curveGenerateKeyPair Proxy Curve_X448
    x448
    groupGenerateKeyPair Group
    FFDHE2048 = Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    gen Params
    ffdhe2048 Int
    exp2048 PrivateNumber -> GroupPrivate
    GroupPri_FFDHE2048 PublicNumber -> GroupPublic
    GroupPub_FFDHE2048
    groupGenerateKeyPair Group
    FFDHE3072 = Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    gen Params
    ffdhe3072 Int
    exp3072 PrivateNumber -> GroupPrivate
    GroupPri_FFDHE3072 PublicNumber -> GroupPublic
    GroupPub_FFDHE3072
    groupGenerateKeyPair Group
    FFDHE4096 = Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    gen Params
    ffdhe4096 Int
    exp4096 PrivateNumber -> GroupPrivate
    GroupPri_FFDHE4096 PublicNumber -> GroupPublic
    GroupPub_FFDHE4096
    groupGenerateKeyPair Group
    FFDHE6144 = Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    gen Params
    ffdhe6144 Int
    exp6144 PrivateNumber -> GroupPrivate
    GroupPri_FFDHE6144 PublicNumber -> GroupPublic
    GroupPub_FFDHE6144
    groupGenerateKeyPair Group
    FFDHE8192 = Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    gen Params
    ffdhe8192 Int
    exp8192 PrivateNumber -> GroupPrivate
    GroupPri_FFDHE8192 PublicNumber -> GroupPublic
    GroupPub_FFDHE8192

    dhGroupGenerateKeyPair :: MonadRandom r => Group -> r (Params, PrivateNumber, PublicNumber)
    dhGroupGenerateKeyPair :: forall (r :: * -> *).
    MonadRandom r =>
    Group -> r (Params, PrivateNumber, PublicNumber)
    dhGroupGenerateKeyPair Group
    FFDHE2048 = Params
    -> r (PrivateNumber, PublicNumber)
    -> r (Params, PrivateNumber, PublicNumber)
    forall (f :: * -> *) a b.
    Functor f =>
    Params -> f (a, b) -> f (Params, a, b)
    addParams Params
    ffdhe2048 (Params -> Int -> r (PrivateNumber, PublicNumber)
    forall (r :: * -> *).
    MonadRandom r =>
    Params -> Int -> r (PrivateNumber, PublicNumber)
    gen' Params
    ffdhe2048 Int
    exp2048)
    dhGroupGenerateKeyPair Group
    FFDHE3072 = Params
    -> r (PrivateNumber, PublicNumber)
    -> r (Params, PrivateNumber, PublicNumber)
    forall (f :: * -> *) a b.
    Functor f =>
    Params -> f (a, b) -> f (Params, a, b)
    addParams Params
    ffdhe3072 (Params -> Int -> r (PrivateNumber, PublicNumber)
    forall (r :: * -> *).
    MonadRandom r =>
    Params -> Int -> r (PrivateNumber, PublicNumber)
    gen' Params
    ffdhe3072 Int
    exp3072)
    dhGroupGenerateKeyPair Group
    FFDHE4096 = Params
    -> r (PrivateNumber, PublicNumber)
    -> r (Params, PrivateNumber, PublicNumber)
    forall (f :: * -> *) a b.
    Functor f =>
    Params -> f (a, b) -> f (Params, a, b)
    addParams Params
    ffdhe4096 (Params -> Int -> r (PrivateNumber, PublicNumber)
    forall (r :: * -> *).
    MonadRandom r =>
    Params -> Int -> r (PrivateNumber, PublicNumber)
    gen' Params
    ffdhe4096 Int
    exp4096)
    dhGroupGenerateKeyPair Group
    FFDHE6144 = Params
    -> r (PrivateNumber, PublicNumber)
    -> r (Params, PrivateNumber, PublicNumber)
    forall (f :: * -> *) a b.
    Functor f =>
    Params -> f (a, b) -> f (Params, a, b)
    addParams Params
    ffdhe6144 (Params -> Int -> r (PrivateNumber, PublicNumber)
    forall (r :: * -> *).
    MonadRandom r =>
    Params -> Int -> r (PrivateNumber, PublicNumber)
    gen' Params
    ffdhe6144 Int
    exp6144)
    dhGroupGenerateKeyPair Group
    FFDHE8192 = Params
    -> r (PrivateNumber, PublicNumber)
    -> r (Params, PrivateNumber, PublicNumber)
    forall (f :: * -> *) a b.
    Functor f =>
    Params -> f (a, b) -> f (Params, a, b)
    addParams Params
    ffdhe8192 (Params -> Int -> r (PrivateNumber, PublicNumber)
    forall (r :: * -> *).
    MonadRandom r =>
    Params -> Int -> r (PrivateNumber, PublicNumber)
    gen' Params
    ffdhe8192 Int
    exp8192)
    dhGroupGenerateKeyPair Group
    grp       = String -> r (Params, PrivateNumber, PublicNumber)
    forall a. HasCallStack => String -> a
    error (String
    "invalid FFDHE group: " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Group -> String
    forall a. Show a => a -> String
    show Group
    grp)

    addParams :: Functor f => Params -> f (a, b) -> f (Params, a, b)
    addParams :: forall (f :: * -> *) a b.
    Functor f =>
    Params -> f (a, b) -> f (Params, a, b)
    addParams Params
    params = ((a, b) -> (Params, a, b)) -> f (a, b) -> f (Params, a, b)
    forall a b. (a -> b) -> f a -> f b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (((a, b) -> (Params, a, b)) -> f (a, b) -> f (Params, a, b))
    -> ((a, b) -> (Params, a, b)) -> f (a, b) -> f (Params, a, b)
    forall a b. (a -> b) -> a -> b
    $ \(a
    a, b
    b) -> (Params
    params, a
    a, b
    b)

    fs :: MonadRandom r
       => (Scalar a -> GroupPrivate, Point a -> GroupPublic)
       -> r (KeyPair a)
       -> r (GroupPrivate, GroupPublic)
    (Scalar a -> GroupPrivate
    t1, Point a -> GroupPublic
    t2) fs :: forall (r :: * -> *) a.
    MonadRandom r =>
    (Scalar a -> GroupPrivate, Point a -> GroupPublic)
    -> r (KeyPair a) -> r (GroupPrivate, GroupPublic)
    `fs` r (KeyPair a)
    action = do
        KeyPair a
    keypair <- r (KeyPair a)
    action
        let pub :: Point a
    pub = KeyPair a -> Point a
    forall curve. KeyPair curve -> Point curve
    keypairGetPublic KeyPair a
    keypair
            pri :: Scalar a
    pri = KeyPair a -> Scalar a
    forall curve. KeyPair curve -> Scalar curve
    keypairGetPrivate KeyPair a
    keypair
        (GroupPrivate, GroupPublic) -> r (GroupPrivate, GroupPublic)
    forall a. a -> r a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Scalar a -> GroupPrivate
    t1 Scalar a
    pri, Point a -> GroupPublic
    t2 Point a
    pub)

    gen :: MonadRandom r
        => Params
        -> Int
        -> (PrivateNumber -> GroupPrivate)
        -> (PublicNumber -> GroupPublic)
        -> r (GroupPrivate, GroupPublic)
    gen :: forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> r (GroupPrivate, GroupPublic)
    gen Params
    params Int
    expBits PrivateNumber -> GroupPrivate
    priTag PublicNumber -> GroupPublic
    pubTag = (PrivateNumber -> GroupPrivate
    priTag (PrivateNumber -> GroupPrivate)
    -> (PublicNumber -> GroupPublic)
    -> (PrivateNumber, PublicNumber)
    -> (GroupPrivate, GroupPublic)
    forall b c b' c'. (b -> c) -> (b' -> c') -> (b, b') -> (c, c')
    forall (a :: * -> * -> *) b c b' c'.
    Arrow a =>
    a b c -> a b' c' -> a (b, b') (c, c')
    *** PublicNumber -> GroupPublic
    pubTag) ((PrivateNumber, PublicNumber) -> (GroupPrivate, GroupPublic))
    -> r (PrivateNumber, PublicNumber) -> r (GroupPrivate, GroupPublic)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Params -> Int -> r (PrivateNumber, PublicNumber)
    forall (r :: * -> *).
    MonadRandom r =>
    Params -> Int -> r (PrivateNumber, PublicNumber)
    gen' Params
    params Int
    expBits

    gen' :: MonadRandom r
         => Params
         -> Int
         -> r (PrivateNumber, PublicNumber)
    gen' :: forall (r :: * -> *).
    MonadRandom r =>
    Params -> Int -> r (PrivateNumber, PublicNumber)
    gen' Params
    params Int
    expBits = (PrivateNumber -> PrivateNumber
    forall a. a -> a
    id (PrivateNumber -> PrivateNumber)
    -> (PrivateNumber -> PublicNumber)
    -> PrivateNumber
    -> (PrivateNumber, PublicNumber)
    forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
    forall (a :: * -> * -> *) b c c'.
    Arrow a =>
    a b c -> a b c' -> a b (c, c')
    &&& Params -> PrivateNumber -> PublicNumber
    calculatePublic Params
    params) (PrivateNumber -> (PrivateNumber, PublicNumber))
    -> r PrivateNumber -> r (PrivateNumber, PublicNumber)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Int -> r PrivateNumber
    forall (r :: * -> *). MonadRandom r => Int -> r PrivateNumber
    generatePriv Int
    expBits

    groupGetPubShared :: MonadRandom r => GroupPublic -> r (Maybe (GroupPublic, GroupKey))
    groupGetPubShared :: forall (r :: * -> *).
    MonadRandom r =>
    GroupPublic -> r (Maybe (GroupPublic, GroupKey))
    groupGetPubShared (GroupPub_P256 Point Curve_P256R1
    pub) =
        ((Point, GroupKey) -> (GroupPublic, GroupKey))
    -> Maybe (Point, GroupKey) -> Maybe (GroupPublic, GroupKey)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Point -> GroupPublic)
    -> (Point, GroupKey) -> (GroupPublic, GroupKey)
    forall b c d. (b -> c) -> (b, d) -> (c, d)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first Point -> GroupPublic
    Point Curve_P256R1 -> GroupPublic
    GroupPub_P256) (Maybe (Point, GroupKey) -> Maybe (GroupPublic, GroupKey))
    -> (CryptoFailable (Point, GroupKey) -> Maybe (Point, GroupKey))
    -> CryptoFailable (Point, GroupKey)
    -> Maybe (GroupPublic, GroupKey)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CryptoFailable (Point, GroupKey) -> Maybe (Point, GroupKey)
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable (Point, GroupKey) -> Maybe (GroupPublic, GroupKey))
    -> r (CryptoFailable (Point, GroupKey))
    -> r (Maybe (GroupPublic, GroupKey))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_P256R1
    -> Point Curve_P256R1
    -> r (CryptoFailable (Point Curve_P256R1, GroupKey))
    forall (randomly :: * -> *) curve (proxy :: * -> *).
    (MonadRandom randomly, EllipticCurveDH curve) =>
    proxy curve
    -> Point curve -> randomly (CryptoFailable (Point curve, GroupKey))
    deriveEncrypt Proxy Curve_P256R1
    p256 Point Curve_P256R1
    pub
    groupGetPubShared (GroupPub_P384 Point Curve_P384R1
    pub) =
        ((Point SEC_p384r1, GroupKey) -> (GroupPublic, GroupKey))
    -> Maybe (Point SEC_p384r1, GroupKey)
    -> Maybe (GroupPublic, GroupKey)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Point SEC_p384r1 -> GroupPublic)
    -> (Point SEC_p384r1, GroupKey) -> (GroupPublic, GroupKey)
    forall b c d. (b -> c) -> (b, d) -> (c, d)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first Point Curve_P384R1 -> GroupPublic
    Point SEC_p384r1 -> GroupPublic
    GroupPub_P384) (Maybe (Point SEC_p384r1, GroupKey)
     -> Maybe (GroupPublic, GroupKey))
    -> (CryptoFailable (Point SEC_p384r1, GroupKey)
        -> Maybe (Point SEC_p384r1, GroupKey))
    -> CryptoFailable (Point SEC_p384r1, GroupKey)
    -> Maybe (GroupPublic, GroupKey)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CryptoFailable (Point SEC_p384r1, GroupKey)
    -> Maybe (Point SEC_p384r1, GroupKey)
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable (Point SEC_p384r1, GroupKey)
     -> Maybe (GroupPublic, GroupKey))
    -> r (CryptoFailable (Point SEC_p384r1, GroupKey))
    -> r (Maybe (GroupPublic, GroupKey))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_P384R1
    -> Point Curve_P384R1
    -> r (CryptoFailable (Point Curve_P384R1, GroupKey))
    forall (randomly :: * -> *) curve (proxy :: * -> *).
    (MonadRandom randomly, EllipticCurveDH curve) =>
    proxy curve
    -> Point curve -> randomly (CryptoFailable (Point curve, GroupKey))
    deriveEncrypt Proxy Curve_P384R1
    p384 Point Curve_P384R1
    pub
    groupGetPubShared (GroupPub_P521 Point Curve_P521R1
    pub) =
        ((Point SEC_p521r1, GroupKey) -> (GroupPublic, GroupKey))
    -> Maybe (Point SEC_p521r1, GroupKey)
    -> Maybe (GroupPublic, GroupKey)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Point SEC_p521r1 -> GroupPublic)
    -> (Point SEC_p521r1, GroupKey) -> (GroupPublic, GroupKey)
    forall b c d. (b -> c) -> (b, d) -> (c, d)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first Point Curve_P521R1 -> GroupPublic
    Point SEC_p521r1 -> GroupPublic
    GroupPub_P521) (Maybe (Point SEC_p521r1, GroupKey)
     -> Maybe (GroupPublic, GroupKey))
    -> (CryptoFailable (Point SEC_p521r1, GroupKey)
        -> Maybe (Point SEC_p521r1, GroupKey))
    -> CryptoFailable (Point SEC_p521r1, GroupKey)
    -> Maybe (GroupPublic, GroupKey)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CryptoFailable (Point SEC_p521r1, GroupKey)
    -> Maybe (Point SEC_p521r1, GroupKey)
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable (Point SEC_p521r1, GroupKey)
     -> Maybe (GroupPublic, GroupKey))
    -> r (CryptoFailable (Point SEC_p521r1, GroupKey))
    -> r (Maybe (GroupPublic, GroupKey))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_P521R1
    -> Point Curve_P521R1
    -> r (CryptoFailable (Point Curve_P521R1, GroupKey))
    forall (randomly :: * -> *) curve (proxy :: * -> *).
    (MonadRandom randomly, EllipticCurveDH curve) =>
    proxy curve
    -> Point curve -> randomly (CryptoFailable (Point curve, GroupKey))
    deriveEncrypt Proxy Curve_P521R1
    p521 Point Curve_P521R1
    pub
    groupGetPubShared (GroupPub_X255 Point Curve_X25519
    pub) =
        ((PublicKey, GroupKey) -> (GroupPublic, GroupKey))
    -> Maybe (PublicKey, GroupKey) -> Maybe (GroupPublic, GroupKey)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((PublicKey -> GroupPublic)
    -> (PublicKey, GroupKey) -> (GroupPublic, GroupKey)
    forall b c d. (b -> c) -> (b, d) -> (c, d)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first PublicKey -> GroupPublic
    Point Curve_X25519 -> GroupPublic
    GroupPub_X255) (Maybe (PublicKey, GroupKey) -> Maybe (GroupPublic, GroupKey))
    -> (CryptoFailable (PublicKey, GroupKey)
        -> Maybe (PublicKey, GroupKey))
    -> CryptoFailable (PublicKey, GroupKey)
    -> Maybe (GroupPublic, GroupKey)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CryptoFailable (PublicKey, GroupKey) -> Maybe (PublicKey, GroupKey)
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable (PublicKey, GroupKey)
     -> Maybe (GroupPublic, GroupKey))
    -> r (CryptoFailable (PublicKey, GroupKey))
    -> r (Maybe (GroupPublic, GroupKey))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_X25519
    -> Point Curve_X25519
    -> r (CryptoFailable (Point Curve_X25519, GroupKey))
    forall (randomly :: * -> *) curve (proxy :: * -> *).
    (MonadRandom randomly, EllipticCurveDH curve) =>
    proxy curve
    -> Point curve -> randomly (CryptoFailable (Point curve, GroupKey))
    deriveEncrypt Proxy Curve_X25519
    x25519 Point Curve_X25519
    pub
    groupGetPubShared (GroupPub_X448 Point Curve_X448
    pub) =
        ((PublicKey, GroupKey) -> (GroupPublic, GroupKey))
    -> Maybe (PublicKey, GroupKey) -> Maybe (GroupPublic, GroupKey)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((PublicKey -> GroupPublic)
    -> (PublicKey, GroupKey) -> (GroupPublic, GroupKey)
    forall b c d. (b -> c) -> (b, d) -> (c, d)
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first PublicKey -> GroupPublic
    Point Curve_X448 -> GroupPublic
    GroupPub_X448) (Maybe (PublicKey, GroupKey) -> Maybe (GroupPublic, GroupKey))
    -> (CryptoFailable (PublicKey, GroupKey)
        -> Maybe (PublicKey, GroupKey))
    -> CryptoFailable (PublicKey, GroupKey)
    -> Maybe (GroupPublic, GroupKey)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CryptoFailable (PublicKey, GroupKey) -> Maybe (PublicKey, GroupKey)
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable (PublicKey, GroupKey)
     -> Maybe (GroupPublic, GroupKey))
    -> r (CryptoFailable (PublicKey, GroupKey))
    -> r (Maybe (GroupPublic, GroupKey))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_X448
    -> Point Curve_X448
    -> r (CryptoFailable (Point Curve_X448, GroupKey))
    forall (randomly :: * -> *) curve (proxy :: * -> *).
    (MonadRandom randomly, EllipticCurveDH curve) =>
    proxy curve
    -> Point curve -> randomly (CryptoFailable (Point curve, GroupKey))
    deriveEncrypt Proxy Curve_X448
    x448 Point Curve_X448
    pub
    groupGetPubShared (GroupPub_FFDHE2048 PublicNumber
    pub) = Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    getPubShared Params
    ffdhe2048 Int
    exp2048 PublicNumber
    pub PublicNumber -> GroupPublic
    GroupPub_FFDHE2048
    groupGetPubShared (GroupPub_FFDHE3072 PublicNumber
    pub) = Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    getPubShared Params
    ffdhe3072 Int
    exp3072 PublicNumber
    pub PublicNumber -> GroupPublic
    GroupPub_FFDHE3072
    groupGetPubShared (GroupPub_FFDHE4096 PublicNumber
    pub) = Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    getPubShared Params
    ffdhe4096 Int
    exp4096 PublicNumber
    pub PublicNumber -> GroupPublic
    GroupPub_FFDHE4096
    groupGetPubShared (GroupPub_FFDHE6144 PublicNumber
    pub) = Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    getPubShared Params
    ffdhe6144 Int
    exp6144 PublicNumber
    pub PublicNumber -> GroupPublic
    GroupPub_FFDHE6144
    groupGetPubShared (GroupPub_FFDHE8192 PublicNumber
    pub) = Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    getPubShared Params
    ffdhe8192 Int
    exp8192 PublicNumber
    pub PublicNumber -> GroupPublic
    GroupPub_FFDHE8192

    dhGroupGetPubShared :: MonadRandom r => Group -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    dhGroupGetPubShared :: forall (r :: * -> *).
    MonadRandom r =>
    Group -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    dhGroupGetPubShared Group
    FFDHE2048 PublicNumber
    pub = Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    getPubShared' Params
    ffdhe2048 Int
    exp2048 PublicNumber
    pub
    dhGroupGetPubShared Group
    FFDHE3072 PublicNumber
    pub = Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    getPubShared' Params
    ffdhe3072 Int
    exp3072 PublicNumber
    pub
    dhGroupGetPubShared Group
    FFDHE4096 PublicNumber
    pub = Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    getPubShared' Params
    ffdhe4096 Int
    exp4096 PublicNumber
    pub
    dhGroupGetPubShared Group
    FFDHE6144 PublicNumber
    pub = Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    getPubShared' Params
    ffdhe6144 Int
    exp6144 PublicNumber
    pub
    dhGroupGetPubShared Group
    FFDHE8192 PublicNumber
    pub = Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    getPubShared' Params
    ffdhe8192 Int
    exp8192 PublicNumber
    pub
    dhGroupGetPubShared Group
    _         PublicNumber
    _   = Maybe (PublicNumber, SharedKey)
    -> r (Maybe (PublicNumber, SharedKey))
    forall a. a -> r a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (PublicNumber, SharedKey)
    forall a. Maybe a
    Nothing

    getPubShared :: MonadRandom r
                 => Params
                 -> Int
                 -> PublicNumber
                 -> (PublicNumber -> GroupPublic)
                 -> r (Maybe (GroupPublic, GroupKey))
    getPubShared :: forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int
    -> PublicNumber
    -> (PublicNumber -> GroupPublic)
    -> r (Maybe (GroupPublic, GroupKey))
    getPubShared Params
    params Int
    expBits PublicNumber
    pub PublicNumber -> GroupPublic
    pubTag | Bool -> Bool
    not (Params -> PublicNumber -> Bool
    valid Params
    params PublicNumber
    pub) = Maybe (GroupPublic, GroupKey) -> r (Maybe (GroupPublic, GroupKey))
    forall a. a -> r a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (GroupPublic, GroupKey)
    forall a. Maybe a
    Nothing
                                           | Bool
    otherwise = do
        PrivateNumber
    mypri <- Int -> r PrivateNumber
    forall (r :: * -> *). MonadRandom r => Int -> r PrivateNumber
    generatePriv Int
    expBits
        let mypub :: PublicNumber
    mypub = Params -> PrivateNumber -> PublicNumber
    calculatePublic Params
    params PrivateNumber
    mypri
        let SharedKey ScrubbedBytes
    share = Params -> PrivateNumber -> PublicNumber -> SharedKey
    getShared Params
    params PrivateNumber
    mypri PublicNumber
    pub
        Maybe (GroupPublic, GroupKey) -> r (Maybe (GroupPublic, GroupKey))
    forall a. a -> r a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (GroupPublic, GroupKey)
     -> r (Maybe (GroupPublic, GroupKey)))
    -> Maybe (GroupPublic, GroupKey)
    -> r (Maybe (GroupPublic, GroupKey))
    forall a b. (a -> b) -> a -> b
    $ (GroupPublic, GroupKey) -> Maybe (GroupPublic, GroupKey)
    forall a. a -> Maybe a
    Just (PublicNumber -> GroupPublic
    pubTag PublicNumber
    mypub, ScrubbedBytes -> GroupKey
    SharedSecret ScrubbedBytes
    share)

    getPubShared' :: MonadRandom r
                  => Params
                  -> Int
                  -> PublicNumber
                  -> r (Maybe (PublicNumber, SharedKey))
    getPubShared' :: forall (r :: * -> *).
    MonadRandom r =>
    Params
    -> Int -> PublicNumber -> r (Maybe (PublicNumber, SharedKey))
    getPubShared' Params
    params Int
    expBits PublicNumber
    pub
        | Bool -> Bool
    not (Params -> PublicNumber -> Bool
    valid Params
    params PublicNumber
    pub) = Maybe (PublicNumber, SharedKey)
    -> r (Maybe (PublicNumber, SharedKey))
    forall a. a -> r a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (PublicNumber, SharedKey)
    forall a. Maybe a
    Nothing
        | Bool
    otherwise = do
            PrivateNumber
    mypri <- Int -> r PrivateNumber
    forall (r :: * -> *). MonadRandom r => Int -> r PrivateNumber
    generatePriv Int
    expBits
            let share :: ScrubbedBytes
    share = SharedKey -> ScrubbedBytes
    stripLeadingZeros (Params -> PrivateNumber -> PublicNumber -> SharedKey
    getShared Params
    params PrivateNumber
    mypri PublicNumber
    pub)
            Maybe (PublicNumber, SharedKey)
    -> r (Maybe (PublicNumber, SharedKey))
    forall a. a -> r a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (PublicNumber, SharedKey)
     -> r (Maybe (PublicNumber, SharedKey)))
    -> Maybe (PublicNumber, SharedKey)
    -> r (Maybe (PublicNumber, SharedKey))
    forall a b. (a -> b) -> a -> b
    $ (PublicNumber, SharedKey) -> Maybe (PublicNumber, SharedKey)
    forall a. a -> Maybe a
    Just (Params -> PrivateNumber -> PublicNumber
    calculatePublic Params
    params PrivateNumber
    mypri, ScrubbedBytes -> SharedKey
    SharedKey ScrubbedBytes
    share)

    groupGetShared ::  GroupPublic -> GroupPrivate -> Maybe GroupKey
    groupGetShared :: GroupPublic -> GroupPrivate -> Maybe GroupKey
    groupGetShared (GroupPub_P256 Point Curve_P256R1
    pub) (GroupPri_P256 Scalar Curve_P256R1
    pri) = CryptoFailable GroupKey -> Maybe GroupKey
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable GroupKey -> Maybe GroupKey)
    -> CryptoFailable GroupKey -> Maybe GroupKey
    forall a b. (a -> b) -> a -> b
    $ Proxy Curve_P256R1
    -> Point Curve_P256R1
    -> Scalar Curve_P256R1
    -> CryptoFailable GroupKey
    forall curve (proxy :: * -> *).
    EllipticCurveDH curve =>
    proxy curve
    -> Point curve -> Scalar curve -> CryptoFailable GroupKey
    deriveDecrypt Proxy Curve_P256R1
    p256 Point Curve_P256R1
    pub Scalar Curve_P256R1
    pri
    groupGetShared (GroupPub_P384 Point Curve_P384R1
    pub) (GroupPri_P384 Scalar Curve_P384R1
    pri) = CryptoFailable GroupKey -> Maybe GroupKey
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable GroupKey -> Maybe GroupKey)
    -> CryptoFailable GroupKey -> Maybe GroupKey
    forall a b. (a -> b) -> a -> b
    $ Proxy Curve_P384R1
    -> Point Curve_P384R1
    -> Scalar Curve_P384R1
    -> CryptoFailable GroupKey
    forall curve (proxy :: * -> *).
    EllipticCurveDH curve =>
    proxy curve
    -> Point curve -> Scalar curve -> CryptoFailable GroupKey
    deriveDecrypt Proxy Curve_P384R1
    p384 Point Curve_P384R1
    pub Scalar Curve_P384R1
    pri
    groupGetShared (GroupPub_P521 Point Curve_P521R1
    pub) (GroupPri_P521 Scalar Curve_P521R1
    pri) = CryptoFailable GroupKey -> Maybe GroupKey
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable GroupKey -> Maybe GroupKey)
    -> CryptoFailable GroupKey -> Maybe GroupKey
    forall a b. (a -> b) -> a -> b
    $ Proxy Curve_P521R1
    -> Point Curve_P521R1
    -> Scalar Curve_P521R1
    -> CryptoFailable GroupKey
    forall curve (proxy :: * -> *).
    EllipticCurveDH curve =>
    proxy curve
    -> Point curve -> Scalar curve -> CryptoFailable GroupKey
    deriveDecrypt Proxy Curve_P521R1
    p521 Point Curve_P521R1
    pub Scalar Curve_P521R1
    pri
    groupGetShared (GroupPub_X255 Point Curve_X25519
    pub) (GroupPri_X255 Scalar Curve_X25519
    pri) = CryptoFailable GroupKey -> Maybe GroupKey
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable GroupKey -> Maybe GroupKey)
    -> CryptoFailable GroupKey -> Maybe GroupKey
    forall a b. (a -> b) -> a -> b
    $ Proxy Curve_X25519
    -> Point Curve_X25519
    -> Scalar Curve_X25519
    -> CryptoFailable GroupKey
    forall curve (proxy :: * -> *).
    EllipticCurveDH curve =>
    proxy curve
    -> Point curve -> Scalar curve -> CryptoFailable GroupKey
    deriveDecrypt Proxy Curve_X25519
    x25519 Point Curve_X25519
    pub Scalar Curve_X25519
    pri
    groupGetShared (GroupPub_X448 Point Curve_X448
    pub) (GroupPri_X448 Scalar Curve_X448
    pri) = CryptoFailable GroupKey -> Maybe GroupKey
    forall a. CryptoFailable a -> Maybe a
    maybeCryptoError (CryptoFailable GroupKey -> Maybe GroupKey)
    -> CryptoFailable GroupKey -> Maybe GroupKey
    forall a b. (a -> b) -> a -> b
    $ Proxy Curve_X448
    -> Point Curve_X448 -> Scalar Curve_X448 -> CryptoFailable GroupKey
    forall curve (proxy :: * -> *).
    EllipticCurveDH curve =>
    proxy curve
    -> Point curve -> Scalar curve -> CryptoFailable GroupKey
    deriveDecrypt Proxy Curve_X448
    x448 Point Curve_X448
    pub Scalar Curve_X448
    pri
    groupGetShared (GroupPub_FFDHE2048 PublicNumber
    pub) (GroupPri_FFDHE2048 PrivateNumber
    pri) = Params -> PublicNumber -> PrivateNumber -> Maybe GroupKey
    calcShared Params
    ffdhe2048 PublicNumber
    pub PrivateNumber
    pri
    groupGetShared (GroupPub_FFDHE3072 PublicNumber
    pub) (GroupPri_FFDHE3072 PrivateNumber
    pri) = Params -> PublicNumber -> PrivateNumber -> Maybe GroupKey
    calcShared Params
    ffdhe3072 PublicNumber
    pub PrivateNumber
    pri
    groupGetShared (GroupPub_FFDHE4096 PublicNumber
    pub) (GroupPri_FFDHE4096 PrivateNumber
    pri) = Params -> PublicNumber -> PrivateNumber -> Maybe GroupKey
    calcShared Params
    ffdhe4096 PublicNumber
    pub PrivateNumber
    pri
    groupGetShared (GroupPub_FFDHE6144 PublicNumber
    pub) (GroupPri_FFDHE6144 PrivateNumber
    pri) = Params -> PublicNumber -> PrivateNumber -> Maybe GroupKey
    calcShared Params
    ffdhe6144 PublicNumber
    pub PrivateNumber
    pri
    groupGetShared (GroupPub_FFDHE8192 PublicNumber
    pub) (GroupPri_FFDHE8192 PrivateNumber
    pri) = Params -> PublicNumber -> PrivateNumber -> Maybe GroupKey
    calcShared Params
    ffdhe8192 PublicNumber
    pub PrivateNumber
    pri
    groupGetShared GroupPublic
    _ GroupPrivate
    _ = Maybe GroupKey
    forall a. Maybe a
    Nothing

    calcShared :: Params -> PublicNumber -> PrivateNumber -> Maybe SharedSecret
    calcShared :: Params -> PublicNumber -> PrivateNumber -> Maybe GroupKey
    calcShared Params
    params PublicNumber
    pub PrivateNumber
    pri
        | Params -> PublicNumber -> Bool
    valid Params
    params PublicNumber
    pub = GroupKey -> Maybe GroupKey
    forall a. a -> Maybe a
    Just (GroupKey -> Maybe GroupKey) -> GroupKey -> Maybe GroupKey
    forall a b. (a -> b) -> a -> b
    $ ScrubbedBytes -> GroupKey
    SharedSecret ScrubbedBytes
    share
        | Bool
    otherwise        = Maybe GroupKey
    forall a. Maybe a
    Nothing
      where
        SharedKey ScrubbedBytes
    share = Params -> PrivateNumber -> PublicNumber -> SharedKey
    getShared Params
    params PrivateNumber
    pri PublicNumber
    pub

    encodeGroupPublic :: GroupPublic -> ByteString
    encodeGroupPublic :: GroupPublic -> ByteString
    encodeGroupPublic (GroupPub_P256 Point Curve_P256R1
    p) = Proxy Curve_P256R1 -> Point Curve_P256R1 -> ByteString
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> Point curve -> bs
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_P256R1 -> Point Curve_P256R1 -> bs
    encodePoint Proxy Curve_P256R1
    p256 Point Curve_P256R1
    p
    encodeGroupPublic (GroupPub_P384 Point Curve_P384R1
    p) = Proxy Curve_P384R1 -> Point Curve_P384R1 -> ByteString
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> Point curve -> bs
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_P384R1 -> Point Curve_P384R1 -> bs
    encodePoint Proxy Curve_P384R1
    p384 Point Curve_P384R1
    p
    encodeGroupPublic (GroupPub_P521 Point Curve_P521R1
    p) = Proxy Curve_P521R1 -> Point Curve_P521R1 -> ByteString
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> Point curve -> bs
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_P521R1 -> Point Curve_P521R1 -> bs
    encodePoint Proxy Curve_P521R1
    p521 Point Curve_P521R1
    p
    encodeGroupPublic (GroupPub_X255 Point Curve_X25519
    p) = Proxy Curve_X25519 -> Point Curve_X25519 -> ByteString
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> Point curve -> bs
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_X25519 -> Point Curve_X25519 -> bs
    encodePoint Proxy Curve_X25519
    x25519 Point Curve_X25519
    p
    encodeGroupPublic (GroupPub_X448 Point Curve_X448
    p) = Proxy Curve_X448 -> Point Curve_X448 -> ByteString
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> Point curve -> bs
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_X448 -> Point Curve_X448 -> bs
    encodePoint Proxy Curve_X448
    x448 Point Curve_X448
    p
    encodeGroupPublic (GroupPub_FFDHE2048 PublicNumber
    p) = Params -> PublicNumber -> ByteString
    enc Params
    ffdhe2048 PublicNumber
    p
    encodeGroupPublic (GroupPub_FFDHE3072 PublicNumber
    p) = Params -> PublicNumber -> ByteString
    enc Params
    ffdhe3072 PublicNumber
    p
    encodeGroupPublic (GroupPub_FFDHE4096 PublicNumber
    p) = Params -> PublicNumber -> ByteString
    enc Params
    ffdhe4096 PublicNumber
    p
    encodeGroupPublic (GroupPub_FFDHE6144 PublicNumber
    p) = Params -> PublicNumber -> ByteString
    enc Params
    ffdhe6144 PublicNumber
    p
    encodeGroupPublic (GroupPub_FFDHE8192 PublicNumber
    p) = Params -> PublicNumber -> ByteString
    enc Params
    ffdhe8192 PublicNumber
    p

    enc :: Params -> PublicNumber -> ByteString
    enc :: Params -> PublicNumber -> ByteString
    enc Params
    params (PublicNumber Integer
    p) = Int -> Integer -> ByteString
    forall ba. ByteArray ba => Int -> Integer -> ba
    i2ospOf_ ((Params -> Int
    params_bits Params
    params Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    7) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    8) Integer
    p

    decodeGroupPublic :: Group -> ByteString -> Either CryptoError GroupPublic
    decodeGroupPublic :: Group -> ByteString -> Either CryptoError GroupPublic
    decodeGroupPublic Group
    P256   ByteString
    bs = CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a. CryptoFailable a -> Either CryptoError a
    eitherCryptoError (CryptoFailable GroupPublic -> Either CryptoError GroupPublic)
    -> CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ Point -> GroupPublic
    Point Curve_P256R1 -> GroupPublic
    GroupPub_P256 (Point -> GroupPublic)
    -> CryptoFailable Point -> CryptoFailable GroupPublic
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_P256R1
    -> ByteString -> CryptoFailable (Point Curve_P256R1)
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> bs -> CryptoFailable (Point curve)
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_P256R1 -> bs -> CryptoFailable (Point Curve_P256R1)
    decodePoint Proxy Curve_P256R1
    p256 ByteString
    bs
    decodeGroupPublic Group
    P384   ByteString
    bs = CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a. CryptoFailable a -> Either CryptoError a
    eitherCryptoError (CryptoFailable GroupPublic -> Either CryptoError GroupPublic)
    -> CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ Point Curve_P384R1 -> GroupPublic
    Point SEC_p384r1 -> GroupPublic
    GroupPub_P384 (Point SEC_p384r1 -> GroupPublic)
    -> CryptoFailable (Point SEC_p384r1) -> CryptoFailable GroupPublic
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_P384R1
    -> ByteString -> CryptoFailable (Point Curve_P384R1)
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> bs -> CryptoFailable (Point curve)
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_P384R1 -> bs -> CryptoFailable (Point Curve_P384R1)
    decodePoint Proxy Curve_P384R1
    p384 ByteString
    bs
    decodeGroupPublic Group
    P521   ByteString
    bs = CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a. CryptoFailable a -> Either CryptoError a
    eitherCryptoError (CryptoFailable GroupPublic -> Either CryptoError GroupPublic)
    -> CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ Point Curve_P521R1 -> GroupPublic
    Point SEC_p521r1 -> GroupPublic
    GroupPub_P521 (Point SEC_p521r1 -> GroupPublic)
    -> CryptoFailable (Point SEC_p521r1) -> CryptoFailable GroupPublic
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_P521R1
    -> ByteString -> CryptoFailable (Point Curve_P521R1)
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> bs -> CryptoFailable (Point curve)
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_P521R1 -> bs -> CryptoFailable (Point Curve_P521R1)
    decodePoint Proxy Curve_P521R1
    p521 ByteString
    bs
    decodeGroupPublic Group
    X25519 ByteString
    bs = CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a. CryptoFailable a -> Either CryptoError a
    eitherCryptoError (CryptoFailable GroupPublic -> Either CryptoError GroupPublic)
    -> CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ PublicKey -> GroupPublic
    Point Curve_X25519 -> GroupPublic
    GroupPub_X255 (PublicKey -> GroupPublic)
    -> CryptoFailable PublicKey -> CryptoFailable GroupPublic
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_X25519
    -> ByteString -> CryptoFailable (Point Curve_X25519)
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> bs -> CryptoFailable (Point curve)
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_X25519 -> bs -> CryptoFailable (Point Curve_X25519)
    decodePoint Proxy Curve_X25519
    x25519 ByteString
    bs
    decodeGroupPublic Group
    X448 ByteString
    bs = CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a. CryptoFailable a -> Either CryptoError a
    eitherCryptoError (CryptoFailable GroupPublic -> Either CryptoError GroupPublic)
    -> CryptoFailable GroupPublic -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ PublicKey -> GroupPublic
    Point Curve_X448 -> GroupPublic
    GroupPub_X448 (PublicKey -> GroupPublic)
    -> CryptoFailable PublicKey -> CryptoFailable GroupPublic
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Proxy Curve_X448 -> ByteString -> CryptoFailable (Point Curve_X448)
    forall curve bs (proxy :: * -> *).
    (EllipticCurve curve, ByteArray bs) =>
    proxy curve -> bs -> CryptoFailable (Point curve)
    forall bs (proxy :: * -> *).
    ByteArray bs =>
    proxy Curve_X448 -> bs -> CryptoFailable (Point Curve_X448)
    decodePoint Proxy Curve_X448
    x448 ByteString
    bs
    decodeGroupPublic Group
    FFDHE2048 ByteString
    bs = GroupPublic -> Either CryptoError GroupPublic
    forall a b. b -> Either a b
    Right (GroupPublic -> Either CryptoError GroupPublic)
    -> (Integer -> GroupPublic)
    -> Integer
    -> Either CryptoError GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PublicNumber -> GroupPublic
    GroupPub_FFDHE2048 (PublicNumber -> GroupPublic)
    -> (Integer -> PublicNumber) -> Integer -> GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Integer -> PublicNumber
    PublicNumber (Integer -> Either CryptoError GroupPublic)
    -> Integer -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Integer
    forall ba. ByteArrayAccess ba => ba -> Integer
    os2ip ByteString
    bs
    decodeGroupPublic Group
    FFDHE3072 ByteString
    bs = GroupPublic -> Either CryptoError GroupPublic
    forall a b. b -> Either a b
    Right (GroupPublic -> Either CryptoError GroupPublic)
    -> (Integer -> GroupPublic)
    -> Integer
    -> Either CryptoError GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PublicNumber -> GroupPublic
    GroupPub_FFDHE3072 (PublicNumber -> GroupPublic)
    -> (Integer -> PublicNumber) -> Integer -> GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Integer -> PublicNumber
    PublicNumber (Integer -> Either CryptoError GroupPublic)
    -> Integer -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Integer
    forall ba. ByteArrayAccess ba => ba -> Integer
    os2ip ByteString
    bs
    decodeGroupPublic Group
    FFDHE4096 ByteString
    bs = GroupPublic -> Either CryptoError GroupPublic
    forall a b. b -> Either a b
    Right (GroupPublic -> Either CryptoError GroupPublic)
    -> (Integer -> GroupPublic)
    -> Integer
    -> Either CryptoError GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PublicNumber -> GroupPublic
    GroupPub_FFDHE4096 (PublicNumber -> GroupPublic)
    -> (Integer -> PublicNumber) -> Integer -> GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Integer -> PublicNumber
    PublicNumber (Integer -> Either CryptoError GroupPublic)
    -> Integer -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Integer
    forall ba. ByteArrayAccess ba => ba -> Integer
    os2ip ByteString
    bs
    decodeGroupPublic Group
    FFDHE6144 ByteString
    bs = GroupPublic -> Either CryptoError GroupPublic
    forall a b. b -> Either a b
    Right (GroupPublic -> Either CryptoError GroupPublic)
    -> (Integer -> GroupPublic)
    -> Integer
    -> Either CryptoError GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PublicNumber -> GroupPublic
    GroupPub_FFDHE6144 (PublicNumber -> GroupPublic)
    -> (Integer -> PublicNumber) -> Integer -> GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Integer -> PublicNumber
    PublicNumber (Integer -> Either CryptoError GroupPublic)
    -> Integer -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Integer
    forall ba. ByteArrayAccess ba => ba -> Integer
    os2ip ByteString
    bs
    decodeGroupPublic Group
    FFDHE8192 ByteString
    bs = GroupPublic -> Either CryptoError GroupPublic
    forall a b. b -> Either a b
    Right (GroupPublic -> Either CryptoError GroupPublic)
    -> (Integer -> GroupPublic)
    -> Integer
    -> Either CryptoError GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PublicNumber -> GroupPublic
    GroupPub_FFDHE8192 (PublicNumber -> GroupPublic)
    -> (Integer -> PublicNumber) -> Integer -> GroupPublic
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Integer -> PublicNumber
    PublicNumber (Integer -> Either CryptoError GroupPublic)
    -> Integer -> Either CryptoError GroupPublic
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Integer
    forall ba. ByteArrayAccess ba => ba -> Integer
    os2ip ByteString
    bs

    -- Check that group element in not in the 2-element subgroup { 1, p - 1 }.
    -- See RFC 7919 section 3 and NIST SP 56A rev 2 section 5.6.2.3.1.
    valid :: Params -> PublicNumber -> Bool
    valid :: Params -> PublicNumber -> Bool
    valid (Params Integer
    p Integer
    _ Int
    _) (PublicNumber Integer
    y) = Integer
    1 Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    < Integer
    y Bool -> Bool -> Bool
    && Integer
    y Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    < Integer
    p Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    1

    -- strips leading zeros from the result of getShared, as required
    -- for DH(E) premaster secret in SSL/TLS before version 1.3.
    stripLeadingZeros :: SharedKey -> B.ScrubbedBytes
    stripLeadingZeros :: SharedKey -> ScrubbedBytes
    stripLeadingZeros (SharedKey ScrubbedBytes
    sb) = (ScrubbedBytes, ScrubbedBytes) -> ScrubbedBytes
    forall a b. (a, b) -> b
    snd ((ScrubbedBytes, ScrubbedBytes) -> ScrubbedBytes)
    -> (ScrubbedBytes, ScrubbedBytes) -> ScrubbedBytes
    forall a b. (a -> b) -> a -> b
    $ (Word8 -> Bool) -> ScrubbedBytes -> (ScrubbedBytes, ScrubbedBytes)
    forall bs. ByteArray bs => (Word8 -> Bool) -> bs -> (bs, bs)
    B.span (Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == Word8
    0) ScrubbedBytes
    sb

    -- Use short exponents as optimization, see RFC 7919 section 5.2.
    generatePriv :: MonadRandom r => Int -> r PrivateNumber
    generatePriv :: forall (r :: * -> *). MonadRandom r => Int -> r PrivateNumber
    generatePriv Int
    e = Integer -> PrivateNumber
    PrivateNumber (Integer -> PrivateNumber) -> r Integer -> r PrivateNumber
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Int -> Maybe GenTopPolicy -> Bool -> r Integer
    forall (m :: * -> *).
    MonadRandom m =>
    Int -> Maybe GenTopPolicy -> Bool -> m Integer
    generateParams Int
    e (GenTopPolicy -> Maybe GenTopPolicy
    forall a. a -> Maybe a
    Just GenTopPolicy
    SetHighest) Bool
    False

    -- Short exponent bit sizes from RFC 7919 appendix A, rounded to next
    -- multiple of 16 bits, i.e. going through a function like:
    -- let shortExp n = head [ e | i <- [1..], let e = n + i, e `mod` 16 == 0 ]
    exp2048 :: Int
    exp3072 :: Int
    exp4096 :: Int
    exp6144 :: Int
    exp8192 :: Int
    exp2048 :: Int
    exp2048 = Int
    240 -- shortExp 225
    exp3072 :: Int
    exp3072 = Int
    288 -- shortExp 275
    exp4096 :: Int
    exp4096 = Int
    336 -- shortExp 325
    exp6144 :: Int
    exp6144 = Int
    384 -- shortExp 375
    exp8192 :: Int
    exp8192 = Int
    416 -- shortExp 400