{-# LINE 1 "OpenSSL/EVP/Internal.hsc" #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CApiFFI #-}
module OpenSSL.EVP.Internal (
Cipher(..),
EVP_CIPHER,
withCipherPtr,
cipherIvLength,
CipherCtx(..),
EVP_CIPHER_CTX,
newCipherCtx,
withCipherCtxPtr,
withNewCipherCtxPtr,
CryptoMode(..),
cipherSetPadding,
cipherInitBS,
cipherUpdateBS,
cipherFinalBS,
cipherStrictly,
cipherLazily,
Digest(..),
EVP_MD,
withMDPtr,
DigestCtx(..),
EVP_MD_CTX,
withDigestCtxPtr,
digestUpdateBS,
digestFinalBS,
digestFinal,
digestStrictly,
digestLazily,
HmacCtx(..),
HMAC_CTX,
withHmacCtxPtr,
hmacUpdateBS,
hmacFinalBS,
hmacLazily,
VaguePKey(..),
EVP_PKEY,
PKey(..),
createPKey,
wrapPKeyPtr,
withPKeyPtr,
withPKeyPtr',
unsafePKeyToPtr,
touchPKey
) where
import qualified Data.ByteString.Internal as B8
import qualified Data.ByteString.Unsafe as B8
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy.Char8 as L8
import qualified Data.ByteString.Lazy.Internal as L8
{-# LINE 68 "OpenSSL/EVP/Internal.hsc" #-}
import Control.Exception (mask, mask_, bracket, onException)
import Foreign.C.Types (CChar, CUChar)
{-# LINE 71 "OpenSSL/EVP/Internal.hsc" #-}
import Foreign.C.Types (CInt(..), CUInt(..), CSize(..))
{-# LINE 75 "OpenSSL/EVP/Internal.hsc" #-}
import Foreign.Ptr (Ptr, castPtr, FunPtr)
import Foreign.C.String (CString, peekCStringLen)
import Foreign.ForeignPtr
{-# LINE 79 "OpenSSL/EVP/Internal.hsc" #-}
import Foreign.ForeignPtr.Unsafe as Unsafe
{-# LINE 83 "OpenSSL/EVP/Internal.hsc" #-}
import Foreign.Storable (Storable(..))
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array (allocaArray)
import System.IO.Unsafe (unsafeInterleaveIO)
import OpenSSL.Utils
newtype Cipher = Cipher (Ptr EVP_CIPHER)
data {-# CTYPE "openssl/evp.h" "EVP_CIPHER" #-} EVP_CIPHER
withCipherPtr :: Cipher -> (Ptr EVP_CIPHER -> IO a) -> IO a
withCipherPtr :: forall a. Cipher -> (Ptr EVP_CIPHER -> IO a) -> IO a
withCipherPtr (Cipher Ptr EVP_CIPHER
cipherPtr) Ptr EVP_CIPHER -> IO a
f = Ptr EVP_CIPHER -> IO a
f Ptr EVP_CIPHER
cipherPtr
foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_EVP_CIPHER_iv_length"
_iv_length :: Ptr EVP_CIPHER -> CInt
cipherIvLength :: Cipher -> Int
cipherIvLength :: Cipher -> Int
cipherIvLength (Cipher Ptr EVP_CIPHER
cipherPtr) = CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> CInt -> Int
forall a b. (a -> b) -> a -> b
$ Ptr EVP_CIPHER -> CInt
_iv_length Ptr EVP_CIPHER
cipherPtr
newtype CipherCtx = CipherCtx (ForeignPtr EVP_CIPHER_CTX)
data {-# CTYPE "openssl/evp.h" "EVP_CIPHER_CTX" #-} EVP_CIPHER_CTX
foreign import capi unsafe "openssl/evp.h EVP_CIPHER_CTX_new"
_cipher_ctx_new :: IO (Ptr EVP_CIPHER_CTX)
{-# LINE 115 "OpenSSL/EVP/Internal.hsc" #-}
foreign import capi unsafe "openssl/evp.h EVP_CIPHER_CTX_reset"
_cipher_ctx_reset :: Ptr EVP_CIPHER_CTX -> IO ()
{-# LINE 121 "OpenSSL/EVP/Internal.hsc" #-}
foreign import capi unsafe "openssl/evp.h &EVP_CIPHER_CTX_free"
_cipher_ctx_free :: FunPtr (Ptr EVP_CIPHER_CTX -> IO ())
foreign import capi unsafe "openssl/evp.h EVP_CIPHER_CTX_free"
_cipher_ctx_free' :: Ptr EVP_CIPHER_CTX -> IO ()
foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_EVP_CIPHER_CTX_block_size"
_cipher_ctx_block_size :: Ptr EVP_CIPHER_CTX -> CInt
newCipherCtx :: IO CipherCtx
newCipherCtx :: IO CipherCtx
newCipherCtx = IO CipherCtx -> IO CipherCtx
forall a. IO a -> IO a
mask_ (IO CipherCtx -> IO CipherCtx) -> IO CipherCtx -> IO CipherCtx
forall a b. (a -> b) -> a -> b
$ do
ctx <- FinalizerPtr EVP_CIPHER_CTX
-> Ptr EVP_CIPHER_CTX -> IO (ForeignPtr EVP_CIPHER_CTX)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr EVP_CIPHER_CTX
_cipher_ctx_free (Ptr EVP_CIPHER_CTX -> IO (ForeignPtr EVP_CIPHER_CTX))
-> IO (Ptr EVP_CIPHER_CTX) -> IO (ForeignPtr EVP_CIPHER_CTX)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr EVP_CIPHER_CTX -> IO (Ptr EVP_CIPHER_CTX)
forall a. Ptr a -> IO (Ptr a)
failIfNull (Ptr EVP_CIPHER_CTX -> IO (Ptr EVP_CIPHER_CTX))
-> IO (Ptr EVP_CIPHER_CTX) -> IO (Ptr EVP_CIPHER_CTX)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Ptr EVP_CIPHER_CTX)
_cipher_ctx_new
withForeignPtr ctx _cipher_ctx_reset
return $ CipherCtx ctx
withCipherCtxPtr :: CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withCipherCtxPtr :: forall a. CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withCipherCtxPtr (CipherCtx ForeignPtr EVP_CIPHER_CTX
ctx) = ForeignPtr EVP_CIPHER_CTX -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr EVP_CIPHER_CTX
ctx
withNewCipherCtxPtr :: (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withNewCipherCtxPtr :: forall a. (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withNewCipherCtxPtr Ptr EVP_CIPHER_CTX -> IO a
f =
IO (Ptr EVP_CIPHER_CTX)
-> (Ptr EVP_CIPHER_CTX -> IO ())
-> (Ptr EVP_CIPHER_CTX -> IO a)
-> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (Ptr EVP_CIPHER_CTX -> IO (Ptr EVP_CIPHER_CTX)
forall a. Ptr a -> IO (Ptr a)
failIfNull (Ptr EVP_CIPHER_CTX -> IO (Ptr EVP_CIPHER_CTX))
-> IO (Ptr EVP_CIPHER_CTX) -> IO (Ptr EVP_CIPHER_CTX)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Ptr EVP_CIPHER_CTX)
_cipher_ctx_new) Ptr EVP_CIPHER_CTX -> IO ()
_cipher_ctx_free' ((Ptr EVP_CIPHER_CTX -> IO a) -> IO a)
-> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \ Ptr EVP_CIPHER_CTX
p -> do
Ptr EVP_CIPHER_CTX -> IO ()
_cipher_ctx_reset Ptr EVP_CIPHER_CTX
p
Ptr EVP_CIPHER_CTX -> IO a
f Ptr EVP_CIPHER_CTX
p
data CryptoMode = Encrypt | Decrypt
fromCryptoMode :: Num a => CryptoMode -> a
fromCryptoMode :: forall a. Num a => CryptoMode -> a
fromCryptoMode CryptoMode
Encrypt = a
1
fromCryptoMode CryptoMode
Decrypt = a
0
foreign import capi unsafe "openssl/evp.h EVP_CIPHER_CTX_set_padding"
_SetPadding :: Ptr EVP_CIPHER_CTX -> CInt -> IO CInt
cipherSetPadding :: CipherCtx -> Int -> IO CipherCtx
cipherSetPadding :: CipherCtx -> Int -> IO CipherCtx
cipherSetPadding CipherCtx
ctx Int
pad
= do CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO ()) -> IO ()
forall a. CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withCipherCtxPtr CipherCtx
ctx ((Ptr EVP_CIPHER_CTX -> IO ()) -> IO ())
-> (Ptr EVP_CIPHER_CTX -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr EVP_CIPHER_CTX
ctxPtr ->
Ptr EVP_CIPHER_CTX -> CInt -> IO CInt
_SetPadding Ptr EVP_CIPHER_CTX
ctxPtr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
pad)
IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO ()
forall a. (a -> Bool) -> a -> IO ()
failIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
CipherCtx -> IO CipherCtx
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return CipherCtx
ctx
foreign import capi unsafe "openssl/evp.h EVP_CipherInit"
_CipherInit :: Ptr EVP_CIPHER_CTX
-> Ptr EVP_CIPHER
-> CString
-> CString
-> CInt
-> IO CInt
cipherInitBS :: Cipher
-> B8.ByteString
-> B8.ByteString
-> CryptoMode
-> IO CipherCtx
cipherInitBS :: Cipher -> ByteString -> ByteString -> CryptoMode -> IO CipherCtx
cipherInitBS (Cipher Ptr EVP_CIPHER
c) ByteString
key ByteString
iv CryptoMode
mode
= do ctx <- IO CipherCtx
newCipherCtx
withCipherCtxPtr ctx $ \ Ptr EVP_CIPHER_CTX
ctxPtr ->
ByteString -> (CString -> IO ()) -> IO ()
forall a. ByteString -> (CString -> IO a) -> IO a
B8.unsafeUseAsCString ByteString
key ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ CString
keyPtr ->
ByteString -> (CString -> IO ()) -> IO ()
forall a. ByteString -> (CString -> IO a) -> IO a
B8.unsafeUseAsCString ByteString
iv ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ CString
ivPtr ->
Ptr EVP_CIPHER_CTX
-> Ptr EVP_CIPHER -> CString -> CString -> CInt -> IO CInt
_CipherInit Ptr EVP_CIPHER_CTX
ctxPtr Ptr EVP_CIPHER
c CString
keyPtr CString
ivPtr (CryptoMode -> CInt
forall a. Num a => CryptoMode -> a
fromCryptoMode CryptoMode
mode)
IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO ()
forall a. (a -> Bool) -> a -> IO ()
failIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
return ctx
foreign import capi unsafe "openssl/evp.h EVP_CipherUpdate"
_CipherUpdate :: Ptr EVP_CIPHER_CTX -> Ptr CChar -> Ptr CInt
-> Ptr CChar -> CInt -> IO CInt
cipherUpdateBS :: CipherCtx -> B8.ByteString -> IO B8.ByteString
cipherUpdateBS :: CipherCtx -> ByteString -> IO ByteString
cipherUpdateBS CipherCtx
ctx ByteString
inBS =
CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO ByteString) -> IO ByteString
forall a. CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withCipherCtxPtr CipherCtx
ctx ((Ptr EVP_CIPHER_CTX -> IO ByteString) -> IO ByteString)
-> (Ptr EVP_CIPHER_CTX -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr EVP_CIPHER_CTX
ctxPtr ->
ByteString -> (CStringLen -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CStringLen -> IO a) -> IO a
B8.unsafeUseAsCStringLen ByteString
inBS ((CStringLen -> IO ByteString) -> IO ByteString)
-> (CStringLen -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString
inBuf, Int
inLen) ->
let len :: Int
len = Int
inLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Ptr EVP_CIPHER_CTX -> CInt
_cipher_ctx_block_size Ptr EVP_CIPHER_CTX
ctxPtr) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 in
Int -> (Ptr Word8 -> IO Int) -> IO ByteString
B8.createAndTrim Int
len ((Ptr Word8 -> IO Int) -> IO ByteString)
-> (Ptr Word8 -> IO Int) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
outBuf ->
(Ptr CInt -> IO Int) -> IO Int
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CInt -> IO Int) -> IO Int) -> (Ptr CInt -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \Ptr CInt
outLenPtr ->
Ptr EVP_CIPHER_CTX
-> CString -> Ptr CInt -> CString -> CInt -> IO CInt
_CipherUpdate Ptr EVP_CIPHER_CTX
ctxPtr (Ptr Word8 -> CString
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
outBuf) Ptr CInt
outLenPtr CString
inBuf
(Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
inLen)
IO CInt -> (CInt -> IO CInt) -> IO CInt
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
IO CInt -> IO Int -> IO Int
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek Ptr CInt
outLenPtr
foreign import capi unsafe "openssl/evp.h EVP_CipherFinal"
_CipherFinal :: Ptr EVP_CIPHER_CTX -> Ptr CChar -> Ptr CInt -> IO CInt
cipherFinalBS :: CipherCtx -> IO B8.ByteString
cipherFinalBS :: CipherCtx -> IO ByteString
cipherFinalBS CipherCtx
ctx =
CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO ByteString) -> IO ByteString
forall a. CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withCipherCtxPtr CipherCtx
ctx ((Ptr EVP_CIPHER_CTX -> IO ByteString) -> IO ByteString)
-> (Ptr EVP_CIPHER_CTX -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr EVP_CIPHER_CTX
ctxPtr ->
let len :: Int
len = CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> CInt -> Int
forall a b. (a -> b) -> a -> b
$ Ptr EVP_CIPHER_CTX -> CInt
_cipher_ctx_block_size Ptr EVP_CIPHER_CTX
ctxPtr in
Int -> (Ptr Word8 -> IO Int) -> IO ByteString
B8.createAndTrim Int
len ((Ptr Word8 -> IO Int) -> IO ByteString)
-> (Ptr Word8 -> IO Int) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
outBuf ->
(Ptr CInt -> IO Int) -> IO Int
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CInt -> IO Int) -> IO Int) -> (Ptr CInt -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \Ptr CInt
outLenPtr ->
Ptr EVP_CIPHER_CTX -> CString -> Ptr CInt -> IO CInt
_CipherFinal Ptr EVP_CIPHER_CTX
ctxPtr (Ptr Word8 -> CString
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
outBuf) Ptr CInt
outLenPtr
IO CInt -> (CInt -> IO CInt) -> IO CInt
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
IO CInt -> IO Int -> IO Int
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> Int) -> IO CInt -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek Ptr CInt
outLenPtr
cipherStrictly :: CipherCtx -> B8.ByteString -> IO B8.ByteString
cipherStrictly :: CipherCtx -> ByteString -> IO ByteString
cipherStrictly CipherCtx
ctx ByteString
input = do
output' <- CipherCtx -> ByteString -> IO ByteString
cipherUpdateBS CipherCtx
ctx ByteString
input
output'' <- cipherFinalBS ctx
return $ B8.append output' output''
cipherLazily :: CipherCtx -> L8.ByteString -> IO L8.ByteString
cipherLazily :: CipherCtx -> ByteString -> IO ByteString
cipherLazily CipherCtx
ctx (ByteString
L8.Empty) =
CipherCtx -> IO ByteString
cipherFinalBS CipherCtx
ctx IO ByteString -> (ByteString -> IO ByteString) -> IO ByteString
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> IO ByteString)
-> (ByteString -> ByteString) -> ByteString -> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
L8.fromChunks ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return
cipherLazily CipherCtx
ctx (L8.Chunk ByteString
x ByteString
xs) = do
y <- CipherCtx -> ByteString -> IO ByteString
cipherUpdateBS CipherCtx
ctx ByteString
x
ys <- unsafeInterleaveIO $ cipherLazily ctx xs
return $ L8.Chunk y ys
newtype Digest = Digest (Ptr EVP_MD)
data {-# CTYPE "openssl/evp.h" "EVP_MD" #-} EVP_MD
withMDPtr :: Digest -> (Ptr EVP_MD -> IO a) -> IO a
withMDPtr :: forall a. Digest -> (Ptr EVP_MD -> IO a) -> IO a
withMDPtr (Digest Ptr EVP_MD
mdPtr) Ptr EVP_MD -> IO a
f = Ptr EVP_MD -> IO a
f Ptr EVP_MD
mdPtr
newtype DigestCtx = DigestCtx (ForeignPtr EVP_MD_CTX)
data {-# CTYPE "openssl/evp.h" "EVP_MD_CTX" #-} EVP_MD_CTX
{-# LINE 247 "OpenSSL/EVP/Internal.hsc" #-}
foreign import capi unsafe "openssl/evp.h EVP_MD_CTX_new"
_md_ctx_new :: IO (Ptr EVP_MD_CTX)
foreign import capi unsafe "openssl/evp.h EVP_MD_CTX_reset"
_md_ctx_reset :: Ptr EVP_MD_CTX -> IO ()
foreign import capi unsafe "openssl/evp.h &EVP_MD_CTX_free"
_md_ctx_free :: FunPtr (Ptr EVP_MD_CTX -> IO ())
{-# LINE 261 "OpenSSL/EVP/Internal.hsc" #-}
newDigestCtx :: IO DigestCtx
newDigestCtx :: IO DigestCtx
newDigestCtx = IO DigestCtx -> IO DigestCtx
forall a. IO a -> IO a
mask_ (IO DigestCtx -> IO DigestCtx) -> IO DigestCtx -> IO DigestCtx
forall a b. (a -> b) -> a -> b
$ do
ctx <- FinalizerPtr EVP_MD_CTX
-> Ptr EVP_MD_CTX -> IO (ForeignPtr EVP_MD_CTX)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr EVP_MD_CTX
_md_ctx_free (Ptr EVP_MD_CTX -> IO (ForeignPtr EVP_MD_CTX))
-> IO (Ptr EVP_MD_CTX) -> IO (ForeignPtr EVP_MD_CTX)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr EVP_MD_CTX -> IO (Ptr EVP_MD_CTX)
forall a. Ptr a -> IO (Ptr a)
failIfNull (Ptr EVP_MD_CTX -> IO (Ptr EVP_MD_CTX))
-> IO (Ptr EVP_MD_CTX) -> IO (Ptr EVP_MD_CTX)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (Ptr EVP_MD_CTX)
_md_ctx_new
withForeignPtr ctx _md_ctx_reset
return $ DigestCtx ctx
withDigestCtxPtr :: DigestCtx -> (Ptr EVP_MD_CTX -> IO a) -> IO a
withDigestCtxPtr :: forall a. DigestCtx -> (Ptr EVP_MD_CTX -> IO a) -> IO a
withDigestCtxPtr (DigestCtx ForeignPtr EVP_MD_CTX
ctx) = ForeignPtr EVP_MD_CTX -> (Ptr EVP_MD_CTX -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr EVP_MD_CTX
ctx
foreign import capi unsafe "openssl/evp.h EVP_DigestInit"
_DigestInit :: Ptr EVP_MD_CTX -> Ptr EVP_MD -> IO CInt
digestInit :: Digest -> IO DigestCtx
digestInit :: Digest -> IO DigestCtx
digestInit (Digest Ptr EVP_MD
md) = do
ctx <- IO DigestCtx
newDigestCtx
withDigestCtxPtr ctx $ \Ptr EVP_MD_CTX
ctxPtr ->
Ptr EVP_MD_CTX -> Ptr EVP_MD -> IO CInt
_DigestInit Ptr EVP_MD_CTX
ctxPtr Ptr EVP_MD
md
IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO ()
forall a. (a -> Bool) -> a -> IO ()
failIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
IO () -> IO DigestCtx -> IO DigestCtx
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> DigestCtx -> IO DigestCtx
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return DigestCtx
ctx
foreign import capi unsafe "openssl/evp.h EVP_DigestUpdate"
_DigestUpdate :: Ptr EVP_MD_CTX -> Ptr CChar -> CSize -> IO CInt
digestUpdateBS :: DigestCtx -> B8.ByteString -> IO ()
digestUpdateBS :: DigestCtx -> ByteString -> IO ()
digestUpdateBS DigestCtx
ctx ByteString
bs =
DigestCtx -> (Ptr EVP_MD_CTX -> IO ()) -> IO ()
forall a. DigestCtx -> (Ptr EVP_MD_CTX -> IO a) -> IO a
withDigestCtxPtr DigestCtx
ctx ((Ptr EVP_MD_CTX -> IO ()) -> IO ())
-> (Ptr EVP_MD_CTX -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr EVP_MD_CTX
ctxPtr ->
ByteString -> (CStringLen -> IO ()) -> IO ()
forall a. ByteString -> (CStringLen -> IO a) -> IO a
B8.unsafeUseAsCStringLen ByteString
bs ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(CString
buf, Int
len) ->
Ptr EVP_MD_CTX -> CString -> CSize -> IO CInt
_DigestUpdate Ptr EVP_MD_CTX
ctxPtr CString
buf (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
IO CInt -> (CInt -> IO CInt) -> IO CInt
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO CInt
forall a. (a -> Bool) -> a -> IO a
failIf (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
IO CInt -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
foreign import capi unsafe "openssl/evp.h EVP_DigestFinal"
_DigestFinal :: Ptr EVP_MD_CTX -> Ptr CChar -> Ptr CUInt -> IO CInt
digestFinalBS :: DigestCtx -> IO B8.ByteString
digestFinalBS :: DigestCtx -> IO ByteString
digestFinalBS DigestCtx
ctx =
DigestCtx -> (Ptr EVP_MD_CTX -> IO ByteString) -> IO ByteString
forall a. DigestCtx -> (Ptr EVP_MD_CTX -> IO a) -> IO a
withDigestCtxPtr DigestCtx
ctx ((Ptr EVP_MD_CTX -> IO ByteString) -> IO ByteString)
-> (Ptr EVP_MD_CTX -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr EVP_MD_CTX
ctxPtr ->
Int -> (Ptr Word8 -> IO Int) -> IO ByteString
B8.createAndTrim (Int
64) ((Ptr Word8 -> IO Int) -> IO ByteString)
-> (Ptr Word8 -> IO Int) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
bufPtr ->
{-# LINE 302 "OpenSSL/EVP/Internal.hsc" #-}
alloca $ \bufLenPtr -> do
_DigestFinal ctxPtr (castPtr bufPtr) bufLenPtr >>= failIf_ (/= 1)
fromIntegral <$> peek bufLenPtr
digestFinal :: DigestCtx -> IO String
digestFinal :: DigestCtx -> IO String
digestFinal DigestCtx
ctx =
DigestCtx -> (Ptr EVP_MD_CTX -> IO String) -> IO String
forall a. DigestCtx -> (Ptr EVP_MD_CTX -> IO a) -> IO a
withDigestCtxPtr DigestCtx
ctx ((Ptr EVP_MD_CTX -> IO String) -> IO String)
-> (Ptr EVP_MD_CTX -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \Ptr EVP_MD_CTX
ctxPtr ->
Int -> (CString -> IO String) -> IO String
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray (Int
64) ((CString -> IO String) -> IO String)
-> (CString -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \CString
bufPtr ->
{-# LINE 310 "OpenSSL/EVP/Internal.hsc" #-}
alloca $ \bufLenPtr -> do
_DigestFinal ctxPtr bufPtr bufLenPtr >>= failIf_ (/= 1)
bufLen <- fromIntegral <$> peek bufLenPtr
peekCStringLen (bufPtr, bufLen)
digestStrictly :: Digest -> B8.ByteString -> IO DigestCtx
digestStrictly :: Digest -> ByteString -> IO DigestCtx
digestStrictly Digest
md ByteString
input = do
ctx <- Digest -> IO DigestCtx
digestInit Digest
md
digestUpdateBS ctx input
return ctx
digestLazily :: Digest -> L8.ByteString -> IO DigestCtx
digestLazily :: Digest -> ByteString -> IO DigestCtx
digestLazily Digest
md ByteString
lbs = do
ctx <- Digest -> IO DigestCtx
digestInit Digest
md
mapM_ (digestUpdateBS ctx) $ L8.toChunks lbs
return ctx
newtype HmacCtx = HmacCtx (ForeignPtr HMAC_CTX)
data {-# CTYPE "openssl/hmac.h" "HMAC_CTX" #-} HMAC_CTX
foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_HMAC_CTX_new"
_hmac_ctx_new :: IO (Ptr HMAC_CTX)
foreign import capi unsafe "openssl/hmac.h HMAC_Init"
_hmac_init :: Ptr HMAC_CTX -> Ptr () -> CInt -> Ptr EVP_MD -> IO CInt
foreign import capi unsafe "openssl/hmac.h HMAC_Update"
_hmac_update :: Ptr HMAC_CTX -> Ptr CUChar -> CSize -> IO CInt
foreign import capi unsafe "openssl/hmac.h HMAC_Final"
_hmac_final :: Ptr HMAC_CTX -> Ptr CUChar -> Ptr CUInt -> IO CUInt
foreign import capi unsafe "HsOpenSSL &HsOpenSSL_HMAC_CTX_free"
_hmac_ctx_free :: FunPtr (Ptr HMAC_CTX -> IO ())
newHmacCtx :: IO HmacCtx
newHmacCtx :: IO HmacCtx
newHmacCtx = do
ctxPtr <- IO (Ptr HMAC_CTX)
_hmac_ctx_new
HmacCtx <$> newForeignPtr _hmac_ctx_free ctxPtr
withHmacCtxPtr :: HmacCtx -> (Ptr HMAC_CTX -> IO a) -> IO a
withHmacCtxPtr :: forall a. HmacCtx -> (Ptr HMAC_CTX -> IO a) -> IO a
withHmacCtxPtr (HmacCtx ForeignPtr HMAC_CTX
ctx) = ForeignPtr HMAC_CTX -> (Ptr HMAC_CTX -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr HMAC_CTX
ctx
hmacInit :: Digest -> B8.ByteString -> IO HmacCtx
hmacInit :: Digest -> ByteString -> IO HmacCtx
hmacInit (Digest Ptr EVP_MD
md) ByteString
key = do
ctx <- IO HmacCtx
newHmacCtx
withHmacCtxPtr ctx $ \Ptr HMAC_CTX
ctxPtr ->
ByteString -> (CStringLen -> IO HmacCtx) -> IO HmacCtx
forall a. ByteString -> (CStringLen -> IO a) -> IO a
B8.unsafeUseAsCStringLen ByteString
key ((CStringLen -> IO HmacCtx) -> IO HmacCtx)
-> (CStringLen -> IO HmacCtx) -> IO HmacCtx
forall a b. (a -> b) -> a -> b
$ \(CString
keyPtr, Int
keyLen) ->
Ptr HMAC_CTX -> Ptr () -> CInt -> Ptr EVP_MD -> IO CInt
_hmac_init Ptr HMAC_CTX
ctxPtr (CString -> Ptr ()
forall a b. Ptr a -> Ptr b
castPtr CString
keyPtr) (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
keyLen) Ptr EVP_MD
md
IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO ()
forall a. (a -> Bool) -> a -> IO ()
failIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
IO () -> IO HmacCtx -> IO HmacCtx
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> HmacCtx -> IO HmacCtx
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return HmacCtx
ctx
hmacUpdateBS :: HmacCtx -> B8.ByteString -> IO ()
hmacUpdateBS :: HmacCtx -> ByteString -> IO ()
hmacUpdateBS HmacCtx
ctx ByteString
bs = HmacCtx -> (Ptr HMAC_CTX -> IO ()) -> IO ()
forall a. HmacCtx -> (Ptr HMAC_CTX -> IO a) -> IO a
withHmacCtxPtr HmacCtx
ctx ((Ptr HMAC_CTX -> IO ()) -> IO ())
-> (Ptr HMAC_CTX -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr HMAC_CTX
ctxPtr -> do
ByteString -> (CStringLen -> IO ()) -> IO ()
forall a. ByteString -> (CStringLen -> IO a) -> IO a
B8.unsafeUseAsCStringLen ByteString
bs ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(CString
buf, Int
len) ->
Ptr HMAC_CTX -> Ptr CUChar -> CSize -> IO CInt
_hmac_update Ptr HMAC_CTX
ctxPtr (CString -> Ptr CUChar
forall a b. Ptr a -> Ptr b
castPtr CString
buf) (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CInt -> Bool) -> CInt -> IO ()
forall a. (a -> Bool) -> a -> IO ()
failIf_ (CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1)
hmacFinalBS :: HmacCtx -> IO B8.ByteString
hmacFinalBS :: HmacCtx -> IO ByteString
hmacFinalBS HmacCtx
ctx =
HmacCtx -> (Ptr HMAC_CTX -> IO ByteString) -> IO ByteString
forall a. HmacCtx -> (Ptr HMAC_CTX -> IO a) -> IO a
withHmacCtxPtr HmacCtx
ctx ((Ptr HMAC_CTX -> IO ByteString) -> IO ByteString)
-> (Ptr HMAC_CTX -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr HMAC_CTX
ctxPtr ->
Int -> (Ptr Word8 -> IO Int) -> IO ByteString
B8.createAndTrim (Int
64) ((Ptr Word8 -> IO Int) -> IO ByteString)
-> (Ptr Word8 -> IO Int) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
bufPtr ->
{-# LINE 373 "OpenSSL/EVP/Internal.hsc" #-}
alloca $ \bufLenPtr -> do
_hmac_final ctxPtr (castPtr bufPtr) bufLenPtr >>= failIf_ (/= 1)
fromIntegral <$> peek bufLenPtr
hmacLazily :: Digest -> B8.ByteString -> L8.ByteString -> IO HmacCtx
hmacLazily :: Digest -> ByteString -> ByteString -> IO HmacCtx
hmacLazily Digest
md ByteString
key ByteString
lbs = do
ctx <- Digest -> ByteString -> IO HmacCtx
hmacInit Digest
md ByteString
key
mapM_ (hmacUpdateBS ctx) $ L8.toChunks lbs
return ctx
newtype VaguePKey = VaguePKey (ForeignPtr EVP_PKEY)
data {-# CTYPE "openssl/evp.h" "EVP_PKEY" #-} EVP_PKEY
class PKey k where
toPKey :: k -> IO VaguePKey
fromPKey :: VaguePKey -> IO (Maybe k)
pkeySize :: k -> Int
pkeyDefaultMD :: k -> IO Digest
foreign import capi unsafe "openssl/evp.h EVP_PKEY_new"
_pkey_new :: IO (Ptr EVP_PKEY)
foreign import capi unsafe "openssl/evp.h &EVP_PKEY_free"
_pkey_free :: FunPtr (Ptr EVP_PKEY -> IO ())
foreign import capi unsafe "openssl/evp.h EVP_PKEY_free"
_pkey_free' :: Ptr EVP_PKEY -> IO ()
wrapPKeyPtr :: Ptr EVP_PKEY -> IO VaguePKey
wrapPKeyPtr :: Ptr EVP_PKEY -> IO VaguePKey
wrapPKeyPtr = (ForeignPtr EVP_PKEY -> VaguePKey)
-> IO (ForeignPtr EVP_PKEY) -> IO VaguePKey
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ForeignPtr EVP_PKEY -> VaguePKey
VaguePKey (IO (ForeignPtr EVP_PKEY) -> IO VaguePKey)
-> (Ptr EVP_PKEY -> IO (ForeignPtr EVP_PKEY))
-> Ptr EVP_PKEY
-> IO VaguePKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FinalizerPtr EVP_PKEY -> Ptr EVP_PKEY -> IO (ForeignPtr EVP_PKEY)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr EVP_PKEY
_pkey_free
createPKey :: (Ptr EVP_PKEY -> IO a) -> IO VaguePKey
createPKey :: forall a. (Ptr EVP_PKEY -> IO a) -> IO VaguePKey
createPKey Ptr EVP_PKEY -> IO a
f = ((forall a. IO a -> IO a) -> IO VaguePKey) -> IO VaguePKey
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
mask (((forall a. IO a -> IO a) -> IO VaguePKey) -> IO VaguePKey)
-> ((forall a. IO a -> IO a) -> IO VaguePKey) -> IO VaguePKey
forall a b. (a -> b) -> a -> b
$ \forall a. IO a -> IO a
restore -> do
ptr <- IO (Ptr EVP_PKEY)
_pkey_new IO (Ptr EVP_PKEY)
-> (Ptr EVP_PKEY -> IO (Ptr EVP_PKEY)) -> IO (Ptr EVP_PKEY)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr EVP_PKEY -> IO (Ptr EVP_PKEY)
forall a. Ptr a -> IO (Ptr a)
failIfNull
(restore $ f ptr >> return ()) `onException` _pkey_free' ptr
wrapPKeyPtr ptr
withPKeyPtr :: VaguePKey -> (Ptr EVP_PKEY -> IO a) -> IO a
withPKeyPtr :: forall a. VaguePKey -> (Ptr EVP_PKEY -> IO a) -> IO a
withPKeyPtr (VaguePKey ForeignPtr EVP_PKEY
pkey) = ForeignPtr EVP_PKEY -> (Ptr EVP_PKEY -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr EVP_PKEY
pkey
withPKeyPtr' :: PKey k => k -> (Ptr EVP_PKEY -> IO a) -> IO a
withPKeyPtr' :: forall k a. PKey k => k -> (Ptr EVP_PKEY -> IO a) -> IO a
withPKeyPtr' k
k Ptr EVP_PKEY -> IO a
f = do
pk <- k -> IO VaguePKey
forall k. PKey k => k -> IO VaguePKey
toPKey k
k
withPKeyPtr pk f
unsafePKeyToPtr :: VaguePKey -> Ptr EVP_PKEY
unsafePKeyToPtr :: VaguePKey -> Ptr EVP_PKEY
unsafePKeyToPtr (VaguePKey ForeignPtr EVP_PKEY
pkey) = ForeignPtr EVP_PKEY -> Ptr EVP_PKEY
forall a. ForeignPtr a -> Ptr a
Unsafe.unsafeForeignPtrToPtr ForeignPtr EVP_PKEY
pkey
touchPKey :: VaguePKey -> IO ()
touchPKey :: VaguePKey -> IO ()
touchPKey (VaguePKey ForeignPtr EVP_PKEY
pkey) = ForeignPtr EVP_PKEY -> IO ()
forall a. ForeignPtr a -> IO ()
touchForeignPtr ForeignPtr EVP_PKEY
pkey