{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Crypto.HPKE.Setup (
setupBaseS,
setupBaseR,
setupPSKS,
setupPSKR,
setupS,
setupR,
) where
import qualified Control.Exception as E
import Crypto.HPKE.AEAD
import Crypto.HPKE.Context
import Crypto.HPKE.ID
import Crypto.HPKE.KDF
import Crypto.HPKE.KEM
import Crypto.HPKE.KeySchedule
import Crypto.HPKE.Types
setupBaseS
:: KEM_ID
-> KDF_ID
-> AEAD_ID
-> Maybe EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Info
-> IO (EncodedPublicKey, ContextS)
setupBaseS :: KEM_ID
-> KDF_ID
-> AEAD_ID
-> Maybe EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> IO (EncodedPublicKey, ContextS)
setupBaseS KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id Maybe EncodedSecretKey
mskEm Maybe EncodedSecretKey
mskSm EncodedPublicKey
pkRm Suite
info =
HPKEMap
-> Mode
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> Maybe EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> Suite
-> Suite
-> IO (EncodedPublicKey, ContextS)
setupS HPKEMap
defaultHPKEMap Mode
mode KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id Maybe EncodedSecretKey
mskEm Maybe EncodedSecretKey
mskSm EncodedPublicKey
pkRm Suite
info Suite
"" Suite
""
where
mode :: Mode
mode = case Maybe EncodedSecretKey
mskSm of
Maybe EncodedSecretKey
Nothing -> Mode
ModeBase
Maybe EncodedSecretKey
_ -> Mode
ModeAuth
setupBaseR
:: KEM_ID
-> KDF_ID
-> AEAD_ID
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Info
-> IO ContextR
setupBaseR :: KEM_ID
-> KDF_ID
-> AEAD_ID
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> IO ContextR
setupBaseR KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id EncodedSecretKey
skRm Maybe EncodedSecretKey
mskSm EncodedPublicKey
enc Suite
info =
HPKEMap
-> Mode
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> Suite
-> Suite
-> IO ContextR
setupR HPKEMap
defaultHPKEMap Mode
mode KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id EncodedSecretKey
skRm Maybe EncodedSecretKey
mskSm EncodedPublicKey
enc Suite
info Suite
"" Suite
""
where
mode :: Mode
mode = case Maybe EncodedSecretKey
mskSm of
Maybe EncodedSecretKey
Nothing -> Mode
ModeBase
Maybe EncodedSecretKey
_ -> Mode
ModeAuth
setupPSKS
:: KEM_ID
-> KDF_ID
-> AEAD_ID
-> Maybe EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Info
-> PSK
-> PSK_ID
-> IO (EncodedPublicKey, ContextS)
setupPSKS :: KEM_ID
-> KDF_ID
-> AEAD_ID
-> Maybe EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> Suite
-> Suite
-> IO (EncodedPublicKey, ContextS)
setupPSKS KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id Maybe EncodedSecretKey
skRm Maybe EncodedSecretKey
mskSm =
HPKEMap
-> Mode
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> Maybe EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> Suite
-> Suite
-> IO (EncodedPublicKey, ContextS)
setupS HPKEMap
defaultHPKEMap Mode
mode KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id Maybe EncodedSecretKey
skRm Maybe EncodedSecretKey
mskSm
where
mode :: Mode
mode = case Maybe EncodedSecretKey
mskSm of
Maybe EncodedSecretKey
Nothing -> Mode
ModePsk
Maybe EncodedSecretKey
_ -> Mode
ModeAuthPsk
setupPSKR
:: KEM_ID
-> KDF_ID
-> AEAD_ID
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Info
-> PSK
-> PSK_ID
-> IO ContextR
setupPSKR :: KEM_ID
-> KDF_ID
-> AEAD_ID
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> Suite
-> Suite
-> IO ContextR
setupPSKR KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id EncodedSecretKey
skRm Maybe EncodedSecretKey
mskSm =
HPKEMap
-> Mode
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> Suite
-> Suite
-> IO ContextR
setupR HPKEMap
defaultHPKEMap Mode
mode KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id EncodedSecretKey
skRm Maybe EncodedSecretKey
mskSm
where
mode :: Mode
mode = case Maybe EncodedSecretKey
mskSm of
Maybe EncodedSecretKey
Nothing -> Mode
ModePsk
Maybe EncodedSecretKey
_ -> Mode
ModeAuthPsk
setupS
:: HPKEMap
-> Mode
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> Maybe EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Info
-> PSK
-> PSK_ID
-> IO (EncodedPublicKey, ContextS)
setupS :: HPKEMap
-> Mode
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> Maybe EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> Suite
-> Suite
-> IO (EncodedPublicKey, ContextS)
setupS HPKEMap
hpkeMap Mode
mode KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id Maybe EncodedSecretKey
mskEm Maybe EncodedSecretKey
mskSm EncodedPublicKey
pkRm Suite
info Suite
psk Suite
psk_id = do
Mode -> Suite -> Suite -> IO ()
verifyPSKInput Mode
mode Suite
psk Suite
psk_id
let r :: Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
r = HPKEMap
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
look HPKEMap
hpkeMap KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id
Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
-> (((KEMGroup, KDFHash), KDFHash, AEADCipher)
-> IO (EncodedPublicKey, ContextS))
-> IO (EncodedPublicKey, ContextS)
forall v a. Either HPKEError v -> (v -> IO a) -> IO a
throwOnError Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
r ((((KEMGroup, KDFHash), KDFHash, AEADCipher)
-> IO (EncodedPublicKey, ContextS))
-> IO (EncodedPublicKey, ContextS))
-> (((KEMGroup, KDFHash), KDFHash, AEADCipher)
-> IO (EncodedPublicKey, ContextS))
-> IO (EncodedPublicKey, ContextS)
forall a b. (a -> b) -> a -> b
$ \((KEMGroup Proxy c
group, KDFHash h
h), KDFHash h
h', AEADCipher Proxy a
c) -> do
let derive :: KeyDeriveFunction
derive = h -> Suite -> KeyDeriveFunction
forall h.
(HashAlgorithm h, KDF h) =>
h -> Suite -> KeyDeriveFunction
extractAndExpand h
h (Suite -> KeyDeriveFunction) -> Suite -> KeyDeriveFunction
forall a b. (a -> b) -> a -> b
$ KEM_ID -> Suite
suiteKEM KEM_ID
kem_id
encap <- case Maybe EncodedSecretKey
mskEm of
Maybe EncodedSecretKey
Nothing -> Proxy c -> KeyDeriveFunction -> Maybe EncodedSecretKey -> IO Encap
forall group.
(EllipticCurve group, EllipticCurveDH group) =>
Proxy group
-> KeyDeriveFunction -> Maybe EncodedSecretKey -> IO Encap
encapGen Proxy c
group KeyDeriveFunction
derive Maybe EncodedSecretKey
mskSm
Just EncodedSecretKey
skEm -> Encap -> IO Encap
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Encap -> IO Encap) -> Encap -> IO Encap
forall a b. (a -> b) -> a -> b
$ Proxy c
-> KeyDeriveFunction
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> Encap
forall group.
(EllipticCurve group, EllipticCurveDH group) =>
Proxy group
-> KeyDeriveFunction
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> Encap
encapEnv Proxy c
group KeyDeriveFunction
derive EncodedSecretKey
skEm Maybe EncodedSecretKey
mskSm
throwOnError (encap pkRm) $ \(SharedSecret
shared_secret, EncodedPublicKey
enc) -> do
let (Int
nk, Int
nn, Suite -> Seal
seal', Suite -> Seal
_) = Proxy a -> (Int, Int, Suite -> Seal, Suite -> Seal)
forall a.
Aead a =>
Proxy a -> (Int, Int, Suite -> Seal, Suite -> Seal)
aeadParams Proxy a
c
suite' :: Suite
suite' = KEM_ID -> KDF_ID -> AEAD_ID -> Suite
suiteHPKE KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id
keys :: Either HPKEError (Suite, Suite, Int, PRK h)
keys = h
-> Suite
-> Int
-> Int
-> Mode
-> Suite
-> Suite
-> Suite
-> SharedSecret
-> Either HPKEError (Suite, Suite, Int, PRK h)
forall h.
(HashAlgorithm h, KDF h) =>
h
-> Suite
-> Int
-> Int
-> Mode
-> Suite
-> Suite
-> Suite
-> SharedSecret
-> Either HPKEError (Suite, Suite, Int, PRK h)
keySchedule h
h' Suite
suite' Int
nk Int
nn Mode
mode Suite
info Suite
psk Suite
psk_id SharedSecret
shared_secret
Either HPKEError (Suite, Suite, Int, PRK h)
-> ((Suite, Suite, Int, PRK h) -> IO (EncodedPublicKey, ContextS))
-> IO (EncodedPublicKey, ContextS)
forall v a. Either HPKEError v -> (v -> IO a) -> IO a
throwOnError Either HPKEError (Suite, Suite, Int, PRK h)
keys (((Suite, Suite, Int, PRK h) -> IO (EncodedPublicKey, ContextS))
-> IO (EncodedPublicKey, ContextS))
-> ((Suite, Suite, Int, PRK h) -> IO (EncodedPublicKey, ContextS))
-> IO (EncodedPublicKey, ContextS)
forall a b. (a -> b) -> a -> b
$ \(Suite
key, Suite
nonce, Int
_, PRK h
prk) -> do
let expand' :: Suite -> Int -> Suite
expand' = Suite -> PRK h -> Suite -> Suite -> Int -> Suite
forall h. KDF h => Suite -> PRK h -> Suite -> Suite -> Int -> Suite
labeledExpand Suite
suite' PRK h
prk Suite
"sec"
ctx <- Suite
-> Suite
-> (Suite -> Seal)
-> (Suite -> Int -> Suite)
-> IO ContextS
newContextS Suite
key Suite
nonce Suite -> Seal
seal' Suite -> Int -> Suite
expand'
return (enc, ctx)
setupR
:: HPKEMap
-> Mode
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Info
-> PSK
-> PSK_ID
-> IO ContextR
setupR :: HPKEMap
-> Mode
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> EncodedPublicKey
-> Suite
-> Suite
-> Suite
-> IO ContextR
setupR HPKEMap
hpkeMap Mode
mode KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id EncodedSecretKey
skRm Maybe EncodedSecretKey
mskSm EncodedPublicKey
enc Suite
info Suite
psk Suite
psk_id = do
Mode -> Suite -> Suite -> IO ()
verifyPSKInput Mode
mode Suite
psk Suite
psk_id
let r :: Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
r = HPKEMap
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
look HPKEMap
hpkeMap KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id
Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
-> (((KEMGroup, KDFHash), KDFHash, AEADCipher) -> IO ContextR)
-> IO ContextR
forall v a. Either HPKEError v -> (v -> IO a) -> IO a
throwOnError Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
r ((((KEMGroup, KDFHash), KDFHash, AEADCipher) -> IO ContextR)
-> IO ContextR)
-> (((KEMGroup, KDFHash), KDFHash, AEADCipher) -> IO ContextR)
-> IO ContextR
forall a b. (a -> b) -> a -> b
$ \((KEMGroup Proxy c
group, KDFHash h
h), KDFHash h
h', AEADCipher Proxy a
c) -> do
let derive :: KeyDeriveFunction
derive = h -> Suite -> KeyDeriveFunction
forall h.
(HashAlgorithm h, KDF h) =>
h -> Suite -> KeyDeriveFunction
extractAndExpand h
h (Suite -> KeyDeriveFunction) -> Suite -> KeyDeriveFunction
forall a b. (a -> b) -> a -> b
$ KEM_ID -> Suite
suiteKEM KEM_ID
kem_id
decap :: Decap
decap = Proxy c
-> KeyDeriveFunction
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> Decap
forall group.
(EllipticCurve group, EllipticCurveDH group) =>
Proxy group
-> KeyDeriveFunction
-> EncodedSecretKey
-> Maybe EncodedSecretKey
-> Decap
decapEnv Proxy c
group KeyDeriveFunction
derive EncodedSecretKey
skRm Maybe EncodedSecretKey
mskSm
Either HPKEError SharedSecret
-> (SharedSecret -> IO ContextR) -> IO ContextR
forall v a. Either HPKEError v -> (v -> IO a) -> IO a
throwOnError (Decap
decap EncodedPublicKey
enc) ((SharedSecret -> IO ContextR) -> IO ContextR)
-> (SharedSecret -> IO ContextR) -> IO ContextR
forall a b. (a -> b) -> a -> b
$ \SharedSecret
shared_secret -> do
let (Int
nk, Int
nn, Suite -> Seal
_, Suite -> Seal
open') = Proxy a -> (Int, Int, Suite -> Seal, Suite -> Seal)
forall a.
Aead a =>
Proxy a -> (Int, Int, Suite -> Seal, Suite -> Seal)
aeadParams Proxy a
c
suite' :: Suite
suite' = KEM_ID -> KDF_ID -> AEAD_ID -> Suite
suiteHPKE KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id
keys :: Either HPKEError (Suite, Suite, Int, PRK h)
keys = h
-> Suite
-> Int
-> Int
-> Mode
-> Suite
-> Suite
-> Suite
-> SharedSecret
-> Either HPKEError (Suite, Suite, Int, PRK h)
forall h.
(HashAlgorithm h, KDF h) =>
h
-> Suite
-> Int
-> Int
-> Mode
-> Suite
-> Suite
-> Suite
-> SharedSecret
-> Either HPKEError (Suite, Suite, Int, PRK h)
keySchedule h
h' Suite
suite' Int
nk Int
nn Mode
mode Suite
info Suite
psk Suite
psk_id SharedSecret
shared_secret
Either HPKEError (Suite, Suite, Int, PRK h)
-> ((Suite, Suite, Int, PRK h) -> IO ContextR) -> IO ContextR
forall v a. Either HPKEError v -> (v -> IO a) -> IO a
throwOnError Either HPKEError (Suite, Suite, Int, PRK h)
keys (((Suite, Suite, Int, PRK h) -> IO ContextR) -> IO ContextR)
-> ((Suite, Suite, Int, PRK h) -> IO ContextR) -> IO ContextR
forall a b. (a -> b) -> a -> b
$ \(Suite
key, Suite
nonce, Int
_, PRK h
prk) -> do
let expand' :: Suite -> Int -> Suite
expand' = Suite -> PRK h -> Suite -> Suite -> Int -> Suite
forall h. KDF h => Suite -> PRK h -> Suite -> Suite -> Int -> Suite
labeledExpand Suite
suite' PRK h
prk Suite
"sec"
Suite
-> Suite
-> (Suite -> Seal)
-> (Suite -> Int -> Suite)
-> IO ContextR
newContextR Suite
key Suite
nonce Suite -> Seal
open' Suite -> Int -> Suite
expand'
aeadParams
:: Aead a
=> Proxy a -> (Int, Int, Key -> Seal, Key -> Open)
aeadParams :: forall a.
Aead a =>
Proxy a -> (Int, Int, Suite -> Seal, Suite -> Seal)
aeadParams Proxy a
c = (Proxy a -> Int
forall a. Aead a => Proxy a -> Int
nK Proxy a
c, Proxy a -> Int
forall a. Aead a => Proxy a -> Int
nN Proxy a
c, Proxy a -> Suite -> Seal
forall a. Aead a => Proxy a -> Suite -> Seal
sealA Proxy a
c, Proxy a -> Suite -> Seal
forall a. Aead a => Proxy a -> Suite -> Seal
openA Proxy a
c)
throwOnError :: Either HPKEError v -> (v -> IO a) -> IO a
throwOnError :: forall v a. Either HPKEError v -> (v -> IO a) -> IO a
throwOnError (Left HPKEError
err) v -> IO a
_body = HPKEError -> IO a
forall e a. (HasCallStack, Exception e) => e -> IO a
E.throwIO HPKEError
err
throwOnError (Right v
ss) v -> IO a
body = v -> IO a
body v
ss
look
:: HPKEMap
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
look :: HPKEMap
-> KEM_ID
-> KDF_ID
-> AEAD_ID
-> Either HPKEError ((KEMGroup, KDFHash), KDFHash, AEADCipher)
look HPKEMap{[(AEAD_ID, AEADCipher)]
[(KDF_ID, KDFHash)]
[(KEM_ID, (KEMGroup, KDFHash))]
kemMap :: [(KEM_ID, (KEMGroup, KDFHash))]
kdfMap :: [(KDF_ID, KDFHash)]
cipherMap :: [(AEAD_ID, AEADCipher)]
cipherMap :: HPKEMap -> [(AEAD_ID, AEADCipher)]
kdfMap :: HPKEMap -> [(KDF_ID, KDFHash)]
kemMap :: HPKEMap -> [(KEM_ID, (KEMGroup, KDFHash))]
..} KEM_ID
kem_id KDF_ID
kdf_id AEAD_ID
aead_id = do
k <- KEM_ID
-> [(KEM_ID, (KEMGroup, KDFHash))]
-> Either HPKEError (KEMGroup, KDFHash)
forall k v. (Eq k, Show k) => k -> [(k, v)] -> Either HPKEError v
lookupE KEM_ID
kem_id [(KEM_ID, (KEMGroup, KDFHash))]
kemMap
h <- lookupE kdf_id kdfMap
a <- lookupE aead_id cipherMap
return (k, h, a)
verifyPSKInput :: Mode -> PSK -> PSK_ID -> IO ()
verifyPSKInput :: Mode -> Suite -> Suite -> IO ()
verifyPSKInput Mode
mode Suite
psk Suite
psk_id
| Bool
got_psk Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Bool
got_psk_id =
HPKEError -> IO ()
forall e a. (HasCallStack, Exception e) => e -> IO a
E.throwIO (HPKEError -> IO ()) -> HPKEError -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> HPKEError
ValidationError String
"mismatch for psk and psk_id"
| Bool
got_psk Bool -> Bool -> Bool
&& Mode
mode Mode -> [Mode] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Mode
ModeBase, Mode
ModeAuth] =
HPKEError -> IO ()
forall e a. (HasCallStack, Exception e) => e -> IO a
E.throwIO (HPKEError -> IO ()) -> HPKEError -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> HPKEError
ValidationError String
"invalid mode (1)"
| (Bool -> Bool
not Bool
got_psk) Bool -> Bool -> Bool
&& Mode
mode Mode -> [Mode] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Mode
ModePsk, Mode
ModeAuthPsk] =
HPKEError -> IO ()
forall e a. (HasCallStack, Exception e) => e -> IO a
E.throwIO (HPKEError -> IO ()) -> HPKEError -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> HPKEError
ValidationError String
"invalid mode (2)"
| Bool
otherwise = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
got_psk :: Bool
got_psk = Suite
psk Suite -> Suite -> Bool
forall a. Eq a => a -> a -> Bool
/= Suite
""
got_psk_id :: Bool
got_psk_id = Suite
psk_id Suite -> Suite -> Bool
forall a. Eq a => a -> a -> Bool
/= Suite
""
suiteKEM :: KEM_ID -> Suite
suiteKEM :: KEM_ID -> Suite
suiteKEM KEM_ID
kem_id = Suite
"KEM" Suite -> Suite -> Suite
forall a. Semigroup a => a -> a -> a
<> Suite
i
where
i :: Suite
i = Int -> Integer -> Suite
forall ba. ByteArray ba => Int -> Integer -> ba
i2ospOf_ Int
2 (Integer -> Suite) -> Integer -> Suite
forall a b. (a -> b) -> a -> b
$ Word16 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16 -> Integer) -> Word16 -> Integer
forall a b. (a -> b) -> a -> b
$ KEM_ID -> Word16
fromKEM_ID KEM_ID
kem_id
suiteHPKE :: KEM_ID -> KDF_ID -> AEAD_ID -> Suite
suiteHPKE :: KEM_ID -> KDF_ID -> AEAD_ID -> Suite
suiteHPKE KEM_ID
kem_id KDF_ID
hkdf_id AEAD_ID
aead_id = Suite
"HPKE" Suite -> Suite -> Suite
forall a. Semigroup a => a -> a -> a
<> Suite
i0 Suite -> Suite -> Suite
forall a. Semigroup a => a -> a -> a
<> Suite
i1 Suite -> Suite -> Suite
forall a. Semigroup a => a -> a -> a
<> Suite
i2
where
i0 :: Suite
i0 = Int -> Integer -> Suite
forall ba. ByteArray ba => Int -> Integer -> ba
i2ospOf_ Int
2 (Integer -> Suite) -> Integer -> Suite
forall a b. (a -> b) -> a -> b
$ Word16 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16 -> Integer) -> Word16 -> Integer
forall a b. (a -> b) -> a -> b
$ KEM_ID -> Word16
fromKEM_ID KEM_ID
kem_id
i1 :: Suite
i1 = Int -> Integer -> Suite
forall ba. ByteArray ba => Int -> Integer -> ba
i2ospOf_ Int
2 (Integer -> Suite) -> Integer -> Suite
forall a b. (a -> b) -> a -> b
$ Word16 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16 -> Integer) -> Word16 -> Integer
forall a b. (a -> b) -> a -> b
$ KDF_ID -> Word16
fromKDF_ID KDF_ID
hkdf_id
i2 :: Suite
i2 = Int -> Integer -> Suite
forall ba. ByteArray ba => Int -> Integer -> ba
i2ospOf_ Int
2 (Integer -> Suite) -> Integer -> Suite
forall a b. (a -> b) -> a -> b
$ Word16 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16 -> Integer) -> Word16 -> Integer
forall a b. (a -> b) -> a -> b
$ AEAD_ID -> Word16
fromAEAD_ID AEAD_ID
aead_id