{-# LANGUAGE CPP #-}
module Crypto.Nettle.Hash (
HashAlgorithm(..)
, hash
, hash'
, hashLazy
, hashLazy'
, GOSTHASH94
, MD2
, MD4
, MD5
, RIPEMD160
, SHA1
, SHA224
, SHA256
, SHA384
, SHA512
, SHA3_224
, SHA3_256
, SHA3_384
, SHA3_512
) where
import Crypto.Nettle.Hash.ForeignImports
import Crypto.Nettle.Hash.Types
import Nettle.Utils
import Data.SecureMem
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as B
{-# ANN module "HLint: ignore Use camelCase" #-}
nettleHashBlockSize :: NettleHashAlgorithm a => Tagged a Int
nettleHashBlockSize = nha_block_size
nettleHashDigestSize :: NettleHashAlgorithm a => Tagged a Int
nettleHashDigestSize = nha_digest_size
nettleHashName :: NettleHashAlgorithm a => Tagged a String
nettleHashName = nha_name
nettleHashInit :: NettleHashAlgorithm a => a
nettleHashInit = untagSelf $ do
size <- nha_ctx_size
initfun <- nha_init
return $ nha_Ctx $ unsafeCreateSecureMem size $ \ctxptr ->
initfun ctxptr
nettleHashUpdate :: NettleHashAlgorithm a => a -> B.ByteString -> a
nettleHashUpdate c msg = untagSelf $ do
updatefun <- nha_update
return $ nha_Ctx $ unsafeDupablePerformIO $
withSecureMemCopy (nha_ctx c) $ \ctxptr ->
withByteStringPtr msg $ \msglen msgptr ->
updatefun ctxptr msglen msgptr
nettleHashFinalize :: NettleHashAlgorithm a => a -> B.ByteString
nettleHashFinalize c = flip witness c $ do
digestSize <- nha_digest_size
digestfun <- nha_digest
return $ unsafeDupablePerformIO $
B.create digestSize $ \digestptr -> do
_ <- withSecureMemCopy (nha_ctx c) $ \ctxptr ->
digestfun ctxptr (fromIntegral digestSize) digestptr
return ()
class NettleHashAlgorithm a where
nha_ctx_size :: Tagged a Int
nha_block_size :: Tagged a Int
nha_digest_size :: Tagged a Int
nha_name :: Tagged a String
nha_init :: Tagged a NettleHashInit
nha_update :: Tagged a NettleHashUpdate
nha_digest :: Tagged a NettleHashDigest
nha_ctx :: a -> SecureMem
nha_Ctx :: SecureMem -> a
#define INSTANCE_HASH(Typ) \
instance HashAlgorithm Typ where \
{ hashBlockSize = nettleHashBlockSize \
; hashDigestSize = nettleHashDigestSize \
; hashName = nettleHashName \
; hashInit = nettleHashInit \
; hashUpdate = nettleHashUpdate \
; hashFinalize = nettleHashFinalize \
}
data GOSTHASH94 = GOSTHASH94 { gosthash94_ctx :: SecureMem }
instance NettleHashAlgorithm GOSTHASH94 where
nha_ctx_size = Tagged c_gosthash94_ctx_size
nha_block_size = Tagged c_gosthash94_block_size
nha_digest_size = Tagged c_gosthash94_digest_size
nha_name = Tagged "GOSTHAST94"
nha_init = Tagged c_gosthash94_init
nha_update = Tagged c_gosthash94_update
nha_digest = Tagged c_gosthash94_digest
nha_ctx = gosthash94_ctx
nha_Ctx = GOSTHASH94
INSTANCE_HASH(GOSTHASH94)
data MD2 = MD2 { md2_ctx :: SecureMem }
instance NettleHashAlgorithm MD2 where
nha_ctx_size = Tagged c_md2_ctx_size
nha_block_size = Tagged c_md2_block_size
nha_digest_size = Tagged c_md2_digest_size
nha_name = Tagged "MD2"
nha_init = Tagged c_md2_init
nha_update = Tagged c_md2_update
nha_digest = Tagged c_md2_digest
nha_ctx = md2_ctx
nha_Ctx = MD2
INSTANCE_HASH(MD2)
data MD4 = MD4 { md4_ctx :: SecureMem }
instance NettleHashAlgorithm MD4 where
nha_ctx_size = Tagged c_md4_ctx_size
nha_block_size = Tagged c_md4_block_size
nha_digest_size = Tagged c_md4_digest_size
nha_name = Tagged "MD4"
nha_init = Tagged c_md4_init
nha_update = Tagged c_md4_update
nha_digest = Tagged c_md4_digest
nha_ctx = md4_ctx
nha_Ctx = MD4
INSTANCE_HASH(MD4)
data MD5 = MD5 { md5_ctx :: SecureMem }
instance NettleHashAlgorithm MD5 where
nha_ctx_size = Tagged c_md5_ctx_size
nha_block_size = Tagged c_md5_block_size
nha_digest_size = Tagged c_md5_digest_size
nha_name = Tagged "MD5"
nha_init = Tagged c_md5_init
nha_update = Tagged c_md5_update
nha_digest = Tagged c_md5_digest
nha_ctx = md5_ctx
nha_Ctx = MD5
INSTANCE_HASH(MD5)
data RIPEMD160 = RIPEMD160 { ripemd160_ctx :: SecureMem }
instance NettleHashAlgorithm RIPEMD160 where
nha_ctx_size = Tagged c_ripemd160_ctx_size
nha_block_size = Tagged c_ripemd160_block_size
nha_digest_size = Tagged c_ripemd160_digest_size
nha_name = Tagged "RIPEMD160"
nha_init = Tagged c_ripemd160_init
nha_update = Tagged c_ripemd160_update
nha_digest = Tagged c_ripemd160_digest
nha_ctx = ripemd160_ctx
nha_Ctx = RIPEMD160
INSTANCE_HASH(RIPEMD160)
data SHA1 = SHA1 { sha1_ctx :: SecureMem }
instance NettleHashAlgorithm SHA1 where
nha_ctx_size = Tagged c_sha1_ctx_size
nha_block_size = Tagged c_sha1_block_size
nha_digest_size = Tagged c_sha1_digest_size
nha_name = Tagged "SHA1"
nha_init = Tagged c_sha1_init
nha_update = Tagged c_sha1_update
nha_digest = Tagged c_sha1_digest
nha_ctx = sha1_ctx
nha_Ctx = SHA1
INSTANCE_HASH(SHA1)
data SHA224 = SHA224 { sha224_ctx :: SecureMem }
instance NettleHashAlgorithm SHA224 where
nha_ctx_size = Tagged c_sha224_ctx_size
nha_block_size = Tagged c_sha224_block_size
nha_digest_size = Tagged c_sha224_digest_size
nha_name = Tagged "SHA224"
nha_init = Tagged c_sha224_init
nha_update = Tagged c_sha224_update
nha_digest = Tagged c_sha224_digest
nha_ctx = sha224_ctx
nha_Ctx = SHA224
INSTANCE_HASH(SHA224)
data SHA256 = SHA256 { sha256_ctx :: SecureMem }
instance NettleHashAlgorithm SHA256 where
nha_ctx_size = Tagged c_sha256_ctx_size
nha_block_size = Tagged c_sha256_block_size
nha_digest_size = Tagged c_sha256_digest_size
nha_name = Tagged "SHA256"
nha_init = Tagged c_sha256_init
nha_update = Tagged c_sha256_update
nha_digest = Tagged c_sha256_digest
nha_ctx = sha256_ctx
nha_Ctx = SHA256
INSTANCE_HASH(SHA256)
data SHA384 = SHA384 { sha384_ctx :: SecureMem }
instance NettleHashAlgorithm SHA384 where
nha_ctx_size = Tagged c_sha384_ctx_size
nha_block_size = Tagged c_sha384_block_size
nha_digest_size = Tagged c_sha384_digest_size
nha_name = Tagged "SHA384"
nha_init = Tagged c_sha384_init
nha_update = Tagged c_sha384_update
nha_digest = Tagged c_sha384_digest
nha_ctx = sha384_ctx
nha_Ctx = SHA384
INSTANCE_HASH(SHA384)
data SHA512 = SHA512 { sha512_ctx :: SecureMem }
instance NettleHashAlgorithm SHA512 where
nha_ctx_size = Tagged c_sha512_ctx_size
nha_block_size = Tagged c_sha512_block_size
nha_digest_size = Tagged c_sha512_digest_size
nha_name = Tagged "SHA512"
nha_init = Tagged c_sha512_init
nha_update = Tagged c_sha512_update
nha_digest = Tagged c_sha512_digest
nha_ctx = sha512_ctx
nha_Ctx = SHA512
INSTANCE_HASH(SHA512)
data SHA3_224 = SHA3_224 { sha3_224_ctx :: SecureMem }
instance NettleHashAlgorithm SHA3_224 where
nha_ctx_size = Tagged c_sha3_224_ctx_size
nha_block_size = Tagged c_sha3_224_block_size
nha_digest_size = Tagged c_sha3_224_digest_size
nha_name = Tagged "SHA3-224"
nha_init = Tagged c_sha3_224_init
nha_update = Tagged c_sha3_224_update
nha_digest = Tagged c_sha3_224_digest
nha_ctx = sha3_224_ctx
nha_Ctx = SHA3_224
INSTANCE_HASH(SHA3_224)
data SHA3_256 = SHA3_256 { sha3_256_ctx :: SecureMem }
instance NettleHashAlgorithm SHA3_256 where
nha_ctx_size = Tagged c_sha3_256_ctx_size
nha_block_size = Tagged c_sha3_256_block_size
nha_digest_size = Tagged c_sha3_256_digest_size
nha_name = Tagged "SHA3-256"
nha_init = Tagged c_sha3_256_init
nha_update = Tagged c_sha3_256_update
nha_digest = Tagged c_sha3_256_digest
nha_ctx = sha3_256_ctx
nha_Ctx = SHA3_256
INSTANCE_HASH(SHA3_256)
data SHA3_384 = SHA3_384 { sha3_384_ctx :: SecureMem }
instance NettleHashAlgorithm SHA3_384 where
nha_ctx_size = Tagged c_sha3_384_ctx_size
nha_block_size = Tagged c_sha3_384_block_size
nha_digest_size = Tagged c_sha3_384_digest_size
nha_name = Tagged "SHA3-384"
nha_init = Tagged c_sha3_384_init
nha_update = Tagged c_sha3_384_update
nha_digest = Tagged c_sha3_384_digest
nha_ctx = sha3_384_ctx
nha_Ctx = SHA3_384
INSTANCE_HASH(SHA3_384)
data SHA3_512 = SHA3_512 { sha3_512_ctx :: SecureMem }
instance NettleHashAlgorithm SHA3_512 where
nha_ctx_size = Tagged c_sha3_512_ctx_size
nha_block_size = Tagged c_sha3_512_block_size
nha_digest_size = Tagged c_sha3_512_digest_size
nha_name = Tagged "SHA3-512"
nha_init = Tagged c_sha3_512_init
nha_update = Tagged c_sha3_512_update
nha_digest = Tagged c_sha3_512_digest
nha_ctx = sha3_512_ctx
nha_Ctx = SHA3_512
INSTANCE_HASH(SHA3_512)