aboutsummaryrefslogtreecommitdiff
path: root/src/Data/Digest/Internal.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Data/Digest/Internal.hs')
-rw-r--r--src/Data/Digest/Internal.hs92
1 files changed, 0 insertions, 92 deletions
diff --git a/src/Data/Digest/Internal.hs b/src/Data/Digest/Internal.hs
deleted file mode 100644
index 1538276..0000000
--- a/src/Data/Digest/Internal.hs
+++ /dev/null
@@ -1,92 +0,0 @@
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE Rank2Types #-}
-
-module Data.Digest.Internal where
-
-import Control.Exception (assert)
-import Data.Bits (Bits((.&.)), shiftR)
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as ByteString
-import qualified Data.ByteString.Lazy as ByteString.Lazy
-import qualified Data.ByteString.Unsafe as ByteString
-import Data.Char (intToDigit)
-import Data.Word (Word8)
-import Foreign (Ptr, Storable, allocaArray, throwIf_, withForeignPtr)
-import Foreign.C.Types
-import Foreign.Marshal.Unsafe (unsafeLocalState)
-import Unsafe.Coerce (unsafeCoerce)
-
-import Cleanse (mallocCleansablePtr)
-
-type LazyByteString = ByteString.Lazy.ByteString
-
--- | A hash algorithm which follows the standard initialize-update-finalize
--- pattern.
-data Algo = forall ctx. Storable ctx => Algo
- { mdLen :: CSize -- ^ The length of the digest.
- , mdInit :: Ptr ctx -> IO CInt -- ^ Initializes the context. Must return 1.
- -- | Adds the buffer to the context. Must not modify the buffer. Must return
- -- 1.
- , mdUpdate :: forall a. Ptr ctx -> Ptr a -> CSize -> IO CInt
- -- | Adds final padding to the context and writes the digest to the buffer.
- , mdFinal :: Ptr CUChar -> Ptr ctx -> IO CInt
- }
-
--- The type signatures in 'Algo' are suggestive of the functions exposed by the
--- BoringSSL API. Those functions fall into two broad categories--those which
--- always return 1 and those which return 1 only on success.
-
-alwaysSucceeds :: IO CInt -> IO ()
-alwaysSucceeds f = do
- r <- f
- assert (r == 1) (return ())
-
-requireSuccess :: IO CInt -> IO ()
-requireSuccess f = throwIf_ (/= 1) (const "BoringSSL failure") f
-
--- | The result of a hash operation.
-newtype Digest =
- Digest ByteString
- deriving (Eq, Ord)
-
-instance Show Digest where
- show (Digest d) = ByteString.foldr showHexPadded [] d
- where
- showHexPadded b xs =
- hexit (b `shiftR` 4 .&. 0x0f) : hexit (b .&. 0x0f) : xs
- hexit = intToDigit . fromIntegral :: Word8 -> Char
-
--- | Hashes according to the given 'Algo'.
-hash :: Algo -> LazyByteString -> Digest
-hash (Algo {mdLen, mdInit, mdUpdate, mdFinal}) bytes =
- let mdLen' = fromIntegral mdLen :: Int
- in unsafeLocalState $ do
- -- Allocate cleansable space for the hash context. This matches the
- -- behavior of the all-in-one hash functions in BoringSSL (@SHA256@,
- -- @SHA512@, etc.) which cleanse their buffers prior to returning.
- ctxFP <- mallocCleansablePtr
- withForeignPtr ctxFP $ \ctx -> do
- alwaysSucceeds $ mdInit ctx
- mapM_ (updateBytes ctx) (ByteString.Lazy.toChunks bytes)
- d <-
- -- We could allocate another cleansable 'ForeignPtr' to store the
- -- digest, but we're going to be returning a copy of it as a ByteString
- -- anyway, so there's not really any point. Use 'allocaArray'; it's
- -- faster and simpler.
- allocaArray mdLen' $ \mdOut -> do
- requireSuccess $ mdFinal mdOut ctx
- -- 'mdOut' is a 'Ptr CUChar'. However, to make life more interesting,
- -- 'CString' is a 'Ptr CChar', and 'CChar' is signed. This is
- -- especially unfortunate given that all we really want to do is
- -- convert to a 'ByteString', which is unsigned. To work around it,
- -- we're going to cheat and let Haskell reinterpret-cast 'mdOut' to
- -- 'Ptr CChar' before it does its 'ByteString' ingestion.
- ByteString.packCStringLen (unsafeCoerce mdOut, mdLen')
- return (Digest d)
- where
- updateBytes ctx chunk =
- -- 'mdUpdate' treats its @buf@ argument as @const@, so the sharing
- -- inherent in 'ByteString.unsafeUseAsCStringLen' is fine.
- ByteString.unsafeUseAsCStringLen chunk $ \(buf, len) ->
- alwaysSucceeds $ mdUpdate ctx buf (fromIntegral len)