aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbaren@google.com>2018-09-04 18:29:34 -0400
committerGravatar Benjamin Barenblat <bbaren@google.com>2018-09-04 18:29:34 -0400
commit2e7bd84469eba730f24dd3e448cca22f5aed16f4 (patch)
treeb6478cf101c30d956912545eaea411100dccc0f6 /src
parent4e377babaa6203c445607c4bb1cbfd42bd9c6c06 (diff)
Enable error checking for HKDF computations
Diffstat (limited to 'src')
-rw-r--r--src/BTLS/BoringSSL/HKDF.chs5
-rw-r--r--src/BTLS/Buffer.hs25
-rw-r--r--src/Codec/Crypto/HKDF.hs33
3 files changed, 42 insertions, 21 deletions
diff --git a/src/BTLS/BoringSSL/HKDF.chs b/src/BTLS/BoringSSL/HKDF.chs
index 1a28ccc..8ad3df2 100644
--- a/src/BTLS/BoringSSL/HKDF.chs
+++ b/src/BTLS/BoringSSL/HKDF.chs
@@ -22,15 +22,14 @@ import Foreign.C.Types
{#import BTLS.BoringSSL.Base#}
import BTLS.Buffer (unsafeUseAsCBuffer)
-import BTLS.Result
#include <openssl/hkdf.h>
{#fun HKDF_extract as hkdfExtract
{ id `Ptr CUChar', id `Ptr CULong', `Ptr EVPMD'
, unsafeUseAsCBuffer* `ByteString'&, unsafeUseAsCBuffer* `ByteString'& }
- -> `()' requireSuccess*-#}
+ -> `Int'#}
{#fun HKDF_expand as hkdfExpand
{ id `Ptr CUChar', `Int', `Ptr EVPMD', unsafeUseAsCBuffer* `ByteString'&
- , unsafeUseAsCBuffer* `ByteString'& } -> `()' requireSuccess*-#}
+ , unsafeUseAsCBuffer* `ByteString'& } -> `Int'#}
diff --git a/src/BTLS/Buffer.hs b/src/BTLS/Buffer.hs
index 7168a10..354c787 100644
--- a/src/BTLS/Buffer.hs
+++ b/src/BTLS/Buffer.hs
@@ -15,9 +15,11 @@
module BTLS.Buffer
( unsafeUseAsCBuffer
, packCUStringLen
- , onBufferOfMaxSize
+ , onBufferOfMaxSize, onBufferOfMaxSize'
) where
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.Except (ExceptT, runExceptT)
import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Unsafe as ByteString
@@ -44,9 +46,22 @@ onBufferOfMaxSize ::
=> Int
-> (Ptr CUChar -> Ptr size -> IO ())
-> IO ByteString
-onBufferOfMaxSize maxSize f =
+onBufferOfMaxSize maxSize f = do
+ Right r <- onBufferOfMaxSize' maxSize (compose2 lift f)
+ return r
+
+-- | Like 'onBufferOfMaxSize' but may fail.
+onBufferOfMaxSize' ::
+ (Integral size, Storable size)
+ => Int
+ -> (Ptr CUChar -> Ptr size -> ExceptT e IO ())
+ -> IO (Either e ByteString)
+onBufferOfMaxSize' maxSize f =
allocaArray maxSize $ \pOut ->
- alloca $ \pOutLen -> do
+ alloca $ \pOutLen -> runExceptT $ do
f pOut pOutLen
- outLen <- peek pOutLen
- packCUStringLen (pOut, outLen)
+ outLen <- lift $ peek pOutLen
+ lift $ packCUStringLen (pOut, outLen)
+
+compose2 :: (r -> r') -> (a -> b -> r) -> a -> b -> r'
+compose2 f g = \a b -> f (g a b)
diff --git a/src/Codec/Crypto/HKDF.hs b/src/Codec/Crypto/HKDF.hs
index bc1ea61..31d0be3 100644
--- a/src/Codec/Crypto/HKDF.hs
+++ b/src/Codec/Crypto/HKDF.hs
@@ -48,16 +48,23 @@ module Codec.Crypto.HKDF
-- to do so, specify the empty string as the associated data.
, AssociatedData(AssociatedData)
+ -- * Error handling
+ , Error
+
-- * Legacy functions
, md5
) where
+import Control.Monad ((>=>))
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.Except (runExceptT)
import Foreign (allocaArray)
import Foreign.Marshal.Unsafe (unsafeLocalState)
import BTLS.BoringSSL.Digest (evpMaxMDSize)
import BTLS.BoringSSL.HKDF
-import BTLS.Buffer (onBufferOfMaxSize, packCUStringLen)
+import BTLS.Buffer (onBufferOfMaxSize', packCUStringLen)
+import BTLS.Result (Error, check)
import BTLS.Types
( Algorithm(Algorithm), AssociatedData(AssociatedData), Salt(Salt)
, SecretKey(SecretKey), noSalt
@@ -66,7 +73,7 @@ import Data.Digest (md5, sha1, sha224, sha256, sha384, sha512)
-- | Computes an HKDF. It is defined by
--
--- prop> hkdf md salt info len = expand md info len . extract md salt
+-- prop> hkdf md salt info len = extract md salt >=> expand md info len
--
-- but may be faster than calling the two functions individually.
hkdf ::
@@ -75,16 +82,16 @@ hkdf ::
-> AssociatedData
-> Int -- ^ The length of the derived key, in bytes.
-> SecretKey
- -> SecretKey
-hkdf md salt info outLen = expand md info outLen . extract md salt
+ -> Either [Error] SecretKey
+hkdf md salt info outLen = extract md salt >=> expand md info outLen
-- | Computes an HKDF pseudorandom key (PRK).
-extract :: Algorithm -> Salt -> SecretKey -> SecretKey
+extract :: Algorithm -> Salt -> SecretKey -> Either [Error] SecretKey
extract (Algorithm md) (Salt salt) (SecretKey secret) =
- SecretKey $
+ fmap SecretKey $
unsafeLocalState $
- onBufferOfMaxSize evpMaxMDSize $ \pOutKey pOutLen -> do
- hkdfExtract pOutKey pOutLen md secret salt
+ onBufferOfMaxSize' evpMaxMDSize $ \pOutKey pOutLen ->
+ check $ hkdfExtract pOutKey pOutLen md secret salt
-- | Computes HKDF output key material (OKM).
expand ::
@@ -92,10 +99,10 @@ expand ::
-> AssociatedData
-> Int -- ^ The length of the OKM, in bytes.
-> SecretKey
- -> SecretKey
+ -> Either [Error] SecretKey
expand (Algorithm md) (AssociatedData info) outLen (SecretKey secret) =
- SecretKey $
+ fmap SecretKey $
unsafeLocalState $
- allocaArray outLen $ \pOutKey -> do
- hkdfExpand pOutKey outLen md secret info
- packCUStringLen (pOutKey, outLen)
+ allocaArray outLen $ \pOutKey -> runExceptT $ do
+ check $ hkdfExpand pOutKey outLen md secret info
+ lift $ packCUStringLen (pOutKey, outLen)