aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Data/Digest.chs (renamed from src/Data/Digest.hs)29
-rw-r--r--src/Data/Digest/Internal.chs (renamed from src/Data/Digest/Internal.hsc)44
-rw-r--r--src/Data/Hmac.chs (renamed from src/Data/Hmac.hsc)42
-rw-r--r--src/Foreign/Ptr/Cast.hs21
-rw-r--r--src/Foreign/Ptr/ConstantTimeEquals.chs (renamed from src/Foreign/Ptr/ConstantTimeEquals.hs)11
5 files changed, 68 insertions, 79 deletions
diff --git a/src/Data/Digest.hs b/src/Data/Digest.chs
index bec8c4f..09ab518 100644
--- a/src/Data/Digest.hs
+++ b/src/Data/Digest.chs
@@ -26,37 +26,24 @@ module Data.Digest
import Foreign (Ptr)
-import Data.Digest.Internal
+{#import Data.Digest.Internal#}
-
-foreign import ccall "openssl/digest.h EVP_md5" evpMd5 :: Ptr EvpMd
+#include <openssl/digest.h>
md5 :: Algorithm
-md5 = Algorithm evpMd5
-
-
-foreign import ccall "openssl/digest.h EVP_sha1" evpSha1 :: Ptr EvpMd
+md5 = Algorithm {#call pure EVP_md5 as ^#}
sha1 :: Algorithm
-sha1 = Algorithm evpSha1
-
-
-foreign import ccall "openssl/digest.h EVP_sha224" evpSha224 :: Ptr EvpMd
-
-foreign import ccall "openssl/digest.h EVP_sha256" evpSha256 :: Ptr EvpMd
-
-foreign import ccall "openssl/digest.h EVP_sha384" evpSha384 :: Ptr EvpMd
-
-foreign import ccall "openssl/digest.h EVP_sha512" evpSha512 :: Ptr EvpMd
+sha1 = Algorithm {#call pure EVP_sha1 as ^#}
sha224 :: Algorithm
-sha224 = Algorithm evpSha224
+sha224 = Algorithm {#call pure EVP_sha224 as ^#}
sha256 :: Algorithm
-sha256 = Algorithm evpSha256
+sha256 = Algorithm {#call pure EVP_sha256 as ^#}
sha384 :: Algorithm
-sha384 = Algorithm evpSha384
+sha384 = Algorithm {#call pure EVP_sha384 as ^#}
sha512 :: Algorithm
-sha512 = Algorithm evpSha512
+sha512 = Algorithm {#call pure EVP_sha512 as ^#}
diff --git a/src/Data/Digest/Internal.hsc b/src/Data/Digest/Internal.chs
index abd498c..ed4e09e 100644
--- a/src/Data/Digest/Internal.hsc
+++ b/src/Data/Digest/Internal.chs
@@ -12,7 +12,6 @@
-- License for the specific language governing permissions and limitations under
-- the License.
-{-# LANGUAGE CApiFFI #-}
{-# OPTIONS_GHC -Wno-missing-methods #-}
module Data.Digest.Internal where
@@ -33,6 +32,8 @@ import Foreign.C.Types
import Foreign.Marshal.Unsafe (unsafeLocalState)
import Unsafe.Coerce (unsafeCoerce)
+import Foreign.Ptr.Cast (asVoidPtr)
+
type LazyByteString = ByteString.Lazy.ByteString
#include <openssl/digest.h>
@@ -41,39 +42,30 @@ type LazyByteString = ByteString.Lazy.ByteString
-- | The BoringSSL @ENGINE@ type.
data Engine
+{#pointer *ENGINE as 'Ptr Engine' -> Engine nocode#}
noEngine :: Ptr Engine
noEngine = nullPtr
-- | The BoringSSL @EVP_MD@ type, representing a hash algorithm.
data EvpMd
+{#pointer *EVP_MD as 'Ptr EvpMd' -> EvpMd nocode#}
-- | The BoringSSL @EVP_MD_CTX@ type, representing the state of a pending
-- hashing operation.
data EvpMdCtx
+{#pointer *EVP_MD_CTX as 'Ptr EvpMdCtx' -> EvpMdCtx nocode#}
instance Storable EvpMdCtx where
- sizeOf _ = #size EVP_MD_CTX
- alignment _ = #alignment EVP_MD_CTX
+ sizeOf _ = {#sizeof EVP_MD_CTX#}
+ alignment _ = {#alignof EVP_MD_CTX#}
-- Imported functions from BoringSSL. See
-- https://commondatastorage.googleapis.com/chromium-boringssl-docs/digest.h.html
-- for documentation.
-foreign import ccall "openssl/digest.h EVP_MD_CTX_init"
- evpMdCtxInit :: Ptr EvpMdCtx -> IO ()
-
-foreign import ccall "openssl/digest.h EVP_DigestInit_ex"
- evpDigestInitEx' :: Ptr EvpMdCtx -> Ptr EvpMd -> Ptr Engine -> IO CInt
-
-foreign import capi "openssl/digest.h value EVP_MAX_MD_SIZE"
- evpMaxMdSize :: CSize
-
-foreign import ccall "openssl/digest.h EVP_DigestUpdate"
- evpDigestUpdate' :: Ptr EvpMdCtx -> Ptr a -> CSize -> IO CInt
-
-foreign import ccall "openssl/digest.h EVP_DigestFinal_ex"
- evpDigestFinalEx' :: Ptr EvpMdCtx -> Ptr CUChar -> Ptr CUInt -> IO CInt
+evpMaxMdSize :: Int
+evpMaxMdSize = {#const EVP_MAX_MD_SIZE#}
-- Some of these functions return 'CInt' even though they can never fail. Wrap
-- them to prevent warnings.
@@ -83,12 +75,13 @@ alwaysSucceeds f = do
r <- f
assert (r == 1) (return ())
-evpDigestUpdate :: Ptr EvpMdCtx -> Ptr a -> CSize -> IO ()
-evpDigestUpdate ctx md bytes = alwaysSucceeds $ evpDigestUpdate' ctx md bytes
+evpDigestUpdate :: Ptr EvpMdCtx -> Ptr a -> CULong -> IO ()
+evpDigestUpdate ctx md bytes =
+ alwaysSucceeds $ {#call EVP_DigestUpdate as ^#} ctx (asVoidPtr md) bytes
evpDigestFinalEx :: Ptr EvpMdCtx -> Ptr CUChar -> Ptr CUInt -> IO ()
evpDigestFinalEx ctx mdOut outSize =
- alwaysSucceeds $ evpDigestFinalEx' ctx mdOut outSize
+ alwaysSucceeds $ {#call EVP_DigestFinal_ex as ^#} ctx mdOut outSize
-- Convert functions that can in fact fail to throw exceptions instead.
@@ -96,7 +89,8 @@ requireSuccess :: IO CInt -> IO ()
requireSuccess f = throwIf_ (/= 1) (const "BoringSSL failure") f
evpDigestInitEx :: Ptr EvpMdCtx -> Ptr EvpMd -> Ptr Engine -> IO ()
-evpDigestInitEx ctx md engine = requireSuccess $ evpDigestInitEx' ctx md engine
+evpDigestInitEx ctx md engine =
+ requireSuccess $ {#call EVP_DigestInit_ex as ^#} ctx md engine
-- Now we can build a memory-safe allocator.
@@ -104,14 +98,10 @@ evpDigestInitEx ctx md engine = requireSuccess $ evpDigestInitEx' ctx md engine
mallocEvpMdCtx :: IO (ForeignPtr EvpMdCtx)
mallocEvpMdCtx = do
fp <- mallocForeignPtr
- withForeignPtr fp evpMdCtxInit
+ withForeignPtr fp {#call EVP_MD_CTX_init as ^#}
addForeignPtrFinalizer btlsFinalizeEvpMdCtxPtr fp
return fp
-#def void btlsFinalizeEvpMdCtx(EVP_MD_CTX* const ctx) {
- (void)EVP_MD_CTX_cleanup(ctx);
-}
-
foreign import ccall "&btlsFinalizeEvpMdCtx"
btlsFinalizeEvpMdCtxPtr :: FinalizerPtr EvpMdCtx
@@ -141,7 +131,7 @@ hash (Algorithm md) bytes =
evpDigestInitEx ctx md noEngine
mapM_ (updateBytes ctx) (ByteString.Lazy.toChunks bytes)
d <-
- allocaArray (fromIntegral evpMaxMdSize) $ \mdOut ->
+ allocaArray evpMaxMdSize $ \mdOut ->
alloca $ \pOutSize -> do
evpDigestFinalEx ctx mdOut pOutSize
outSize <- fromIntegral <$> peek pOutSize
diff --git a/src/Data/Hmac.hsc b/src/Data/Hmac.chs
index 5be09a8..7ee68d2 100644
--- a/src/Data/Hmac.hsc
+++ b/src/Data/Hmac.chs
@@ -32,10 +32,11 @@ import Foreign.C.Types
import Foreign.Marshal.Unsafe (unsafeLocalState)
import Unsafe.Coerce (unsafeCoerce)
-import Data.Digest.Internal
+{#import Data.Digest.Internal#}
(Algorithm(Algorithm), Digest(Digest), Engine, EvpMd,
alwaysSucceeds, evpMaxMdSize, noEngine, requireSuccess)
-import Foreign.Ptr.ConstantTimeEquals (constantTimeEquals)
+import Foreign.Ptr.Cast (asVoidPtr)
+{#import Foreign.Ptr.ConstantTimeEquals#} (constantTimeEquals)
type LazyByteString = ByteString.Lazy.ByteString
@@ -46,42 +47,33 @@ type LazyByteString = ByteString.Lazy.ByteString
-- | The BoringSSL @HMAC_CTX@ type, representing the state of a pending HMAC
-- operation.
data HmacCtx
+{#pointer *HMAC_CTX as 'Ptr HmacCtx' -> HmacCtx nocode#}
instance Storable HmacCtx where
- sizeOf _ = #size HMAC_CTX
- alignment _ = #alignment HMAC_CTX
+ sizeOf _ = {#sizeof HMAC_CTX#}
+ alignment _ = {#alignof HMAC_CTX#}
-- Imported functions from BoringSSL. See
-- https://commondatastorage.googleapis.com/chromium-boringssl-docs/hmac.h.html
-- for documentation.
-
-foreign import ccall "openssl/hmac.h HMAC_CTX_init"
- hmacCtxInit :: Ptr HmacCtx -> IO ()
-
-foreign import ccall "openssl/hmac.h HMAC_Init_ex"
- hmacInitEx' ::
- Ptr HmacCtx -> Ptr a -> CSize -> Ptr EvpMd -> Ptr Engine -> IO CInt
-
-foreign import ccall "openssl/hmac.h HMAC_Update"
- hmacUpdate' :: Ptr HmacCtx -> Ptr CUChar -> CSize -> IO CInt
-
-foreign import ccall "openssl/hmac.h HMAC_Final"
- hmacFinal' :: Ptr HmacCtx -> Ptr CUChar -> Ptr CUInt -> IO CInt
-
+--
-- Some of these functions return 'CInt' even though they can never fail. Wrap
-- them to prevent warnings.
-hmacUpdate :: Ptr HmacCtx -> Ptr CUChar -> CSize -> IO ()
-hmacUpdate ctx bytes size = alwaysSucceeds $ hmacUpdate' ctx bytes size
+hmacUpdate :: Ptr HmacCtx -> Ptr CUChar -> CULong -> IO ()
+hmacUpdate ctx bytes size =
+ alwaysSucceeds $ {#call HMAC_Update as ^#} ctx bytes size
-- Convert functions that can in fact fail to throw exceptions instead.
-hmacInitEx :: Ptr HmacCtx -> Ptr a -> CSize -> Ptr EvpMd -> Ptr Engine -> IO ()
+hmacInitEx :: Ptr HmacCtx -> Ptr a -> CULong -> Ptr EvpMd -> Ptr Engine -> IO ()
hmacInitEx ctx bytes size md engine =
- requireSuccess $ hmacInitEx' ctx bytes size md engine
+ requireSuccess $
+ {#call HMAC_Init_ex as ^#} ctx (asVoidPtr bytes) size md engine
hmacFinal :: Ptr HmacCtx -> Ptr CUChar -> Ptr CUInt -> IO ()
-hmacFinal ctx out outSize = requireSuccess $ hmacFinal' ctx out outSize
+hmacFinal ctx out outSize =
+ requireSuccess $ {#call HMAC_Final as ^#} ctx out outSize
-- Now we can build a memory-safe allocator.
@@ -89,7 +81,7 @@ hmacFinal ctx out outSize = requireSuccess $ hmacFinal' ctx out outSize
mallocHmacCtx :: IO (ForeignPtr HmacCtx)
mallocHmacCtx = do
fp <- mallocForeignPtr
- withForeignPtr fp hmacCtxInit
+ withForeignPtr fp {#call HMAC_CTX_init as ^#}
addForeignPtrFinalizer hmacCtxCleanup fp
return fp
@@ -127,7 +119,7 @@ hmac (Algorithm md) (SecretKey key) bytes =
hmacInitEx ctx keyBytes (fromIntegral keySize) md noEngine
mapM_ (updateBytes ctx) (ByteString.Lazy.toChunks bytes)
m <-
- allocaArray (fromIntegral evpMaxMdSize) $ \hmacOut ->
+ allocaArray evpMaxMdSize $ \hmacOut ->
alloca $ \pOutSize -> do
hmacFinal ctx hmacOut pOutSize
outSize <- fromIntegral <$> peek pOutSize
diff --git a/src/Foreign/Ptr/Cast.hs b/src/Foreign/Ptr/Cast.hs
new file mode 100644
index 0000000..653604a
--- /dev/null
+++ b/src/Foreign/Ptr/Cast.hs
@@ -0,0 +1,21 @@
+-- Copyright 2018 Google LLC
+--
+-- Licensed under the Apache License, Version 2.0 (the "License"); you may not
+-- use this file except in compliance with the License. You may obtain a copy of
+-- the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+-- License for the specific language governing permissions and limitations under
+-- the License.
+
+module Foreign.Ptr.Cast where
+
+import Foreign (Ptr)
+import Unsafe.Coerce (unsafeCoerce)
+
+asVoidPtr :: Ptr a -> Ptr ()
+asVoidPtr = unsafeCoerce
diff --git a/src/Foreign/Ptr/ConstantTimeEquals.hs b/src/Foreign/Ptr/ConstantTimeEquals.chs
index 0bd24e7..6b34e7b 100644
--- a/src/Foreign/Ptr/ConstantTimeEquals.hs
+++ b/src/Foreign/Ptr/ConstantTimeEquals.chs
@@ -12,20 +12,19 @@
-- License for the specific language governing permissions and limitations under
-- the License.
-{-# LANGUAGE ScopedTypeVariables #-}
-
module Foreign.Ptr.ConstantTimeEquals where
import Foreign (Ptr)
import Foreign.C.Types
-foreign import ccall "openssl/mem.h CRYPTO_memcmp"
- cryptoMemcmp :: Ptr a -> Ptr a -> CSize -> IO CInt
+import Foreign.Ptr.Cast (asVoidPtr)
+
+#include <openssl/mem.h>
-- | Directly compares two buffers for equality. This operation takes an amount
-- of time dependent on the specified size but independent of either buffer's
-- contents.
constantTimeEquals :: Ptr a -> Ptr a -> Int -> IO Bool
constantTimeEquals a b size =
- let size' = fromIntegral size :: CSize
- in (== 0) <$> cryptoMemcmp a b size'
+ let size' = fromIntegral size :: CULong
+ in (== 0) <$> {#call CRYPTO_memcmp as ^#} (asVoidPtr a) (asVoidPtr b) size'