diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for the hashes package
 
+## 0.2.1.0 -- 2021-10-22
+
+*   Add OpenSSL based implementation of Keccak-512.
+
 ## 0.2.0.0 -- 2021-10-20
 
 Breaking changes:
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -37,5 +37,9 @@
 *   BLAKE2
     *   BLAKE2s256
     *   BLAKE2b512
-*   KECCAK-256 (cf. comment in [Data.Hash.Keccak](https://github.com/larskuhtz/hs-hashes/blob/main/src/Data/Hash/Keccak.hs))
+*   KECCAK
+    *   KECCAK-256
+    *   KECCAK-512
+    See comment in [Data.Hash.Keccak](https://github.com/larskuhtz/hs-hashes/blob/main/src/Data/Hash/Keccak.hs) before using these Keccak implementations.
+
 
diff --git a/cbits/keccak.c b/cbits/keccak.c
--- a/cbits/keccak.c
+++ b/cbits/keccak.c
@@ -35,16 +35,13 @@
 /* *************************************************************************** */
 /* KECCAK-256 for OpenSSL 3.0 */
 
-typedef struct keccak1600_ctx_st KECCAK1600_CTX;
-typedef KECCAK1600_CTX KECCAK256_CTX;
-
 extern const OSSL_DISPATCH ossl_sha3_256_functions[];
+extern const OSSL_DISPATCH ossl_sha3_512_functions[];
 extern int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen);
 
 typedef void (*VoidFunPtr) (void);
 
-VoidFunPtr dispatch(int fn_id) {
-    const OSSL_DISPATCH *fns = ossl_sha3_256_functions;
+VoidFunPtr dispatch(const OSSL_DISPATCH *fns, int fn_id) {
     for (; fns->function_id != 0; fns++) {
         if (fns->function_id == fn_id) {
             return fns->function;
@@ -53,35 +50,72 @@
     return NULL;
 }
 
+VoidFunPtr dispatch256(int fn_id) {
+    return dispatch(ossl_sha3_256_functions, fn_id);
+}
+
+VoidFunPtr dispatch512(int fn_id) {
+    return dispatch(ossl_sha3_512_functions, fn_id);
+}
+
 KECCAK256_CTX *keccak256_newctx()
 {
-    KECCAK256_CTX * ctx = ((OSSL_FUNC_digest_newctx_fn *) dispatch(OSSL_FUNC_DIGEST_NEWCTX))(NULL);
+    KECCAK256_CTX * ctx = ((OSSL_FUNC_digest_newctx_fn *) dispatch256(OSSL_FUNC_DIGEST_NEWCTX))(NULL);
 
     // this has already be called once by the dispatch function. Here we update the pad character
     if (ctx) ossl_sha3_init(ctx, '\x01', 256);
     return ctx;
 }
 
+KECCAK512_CTX *keccak512_newctx()
+{
+    KECCAK512_CTX * ctx = ((OSSL_FUNC_digest_newctx_fn *) dispatch512(OSSL_FUNC_DIGEST_NEWCTX))(NULL);
+
+    // this has already be called once by the dispatch function. Here we update the pad character
+    if (ctx) ossl_sha3_init(ctx, '\x01', 512);
+    return ctx;
+}
+
 int keccak256_init(KECCAK256_CTX *ctx) {
-    return ((OSSL_FUNC_digest_init_fn *) dispatch(OSSL_FUNC_DIGEST_INIT))(ctx, NULL);
+    return ((OSSL_FUNC_digest_init_fn *) dispatch256(OSSL_FUNC_DIGEST_INIT))(ctx, NULL);
 }
 
+int keccak512_init(KECCAK256_CTX *ctx) {
+    return ((OSSL_FUNC_digest_init_fn *) dispatch512(OSSL_FUNC_DIGEST_INIT))(ctx, NULL);
+}
+
 int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l)
 {
-    return ((OSSL_FUNC_digest_update_fn *) dispatch(OSSL_FUNC_DIGEST_UPDATE))(ctx, p, l);
+    return ((OSSL_FUNC_digest_update_fn *) dispatch256(OSSL_FUNC_DIGEST_UPDATE))(ctx, p, l);
 }
 
+int keccak512_update(KECCAK512_CTX *ctx, const void *p, size_t l)
+{
+    return ((OSSL_FUNC_digest_update_fn *) dispatch512(OSSL_FUNC_DIGEST_UPDATE))(ctx, p, l);
+}
+
 int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md)
 {
     size_t l;
-    return ((OSSL_FUNC_digest_final_fn *) dispatch(OSSL_FUNC_DIGEST_FINAL))(ctx, md, &l, 32);
+    return ((OSSL_FUNC_digest_final_fn *) dispatch256(OSSL_FUNC_DIGEST_FINAL))(ctx, md, &l, 32);
 }
 
+int keccak512_final(KECCAK512_CTX *ctx, unsigned char *md)
+{
+    size_t l;
+    return ((OSSL_FUNC_digest_final_fn *) dispatch512(OSSL_FUNC_DIGEST_FINAL))(ctx, md, &l, 64);
+}
+
 void keccak256_freectx(KECCAK256_CTX *ctx)
 {
-    return ((OSSL_FUNC_digest_freectx_fn *) dispatch(OSSL_FUNC_DIGEST_FREECTX))(ctx);
+    return ((OSSL_FUNC_digest_freectx_fn *) dispatch256(OSSL_FUNC_DIGEST_FREECTX))(ctx);
 }
 
+void keccak512_freectx(KECCAK512_CTX *ctx)
+{
+    return ((OSSL_FUNC_digest_freectx_fn *) dispatch512(OSSL_FUNC_DIGEST_FREECTX))(ctx);
+}
+
 #elif OPENSSL_VERSION_NUMBER >= 0x10100000L
 /* *************************************************************************** */
 /* OpenSSL 1.1 */
@@ -105,13 +139,16 @@
 //     unsigned char pad;
 // };
 
-typedef EVP_MD_CTX KECCAK256_CTX;
-
 KECCAK256_CTX *keccak256_newctx()
 {
     return EVP_MD_CTX_new();
 }
 
+KECCAK512_CTX *keccak512_newctx()
+{
+    return EVP_MD_CTX_new();
+}
+
 int keccak256_init(KECCAK256_CTX *ctx) {
     int ok = 1;
     const EVP_MD *md = NULL;
@@ -125,18 +162,47 @@
     return ok;
 }
 
+int keccak512_init(KECCAK512_CTX *ctx) {
+    int ok = 1;
+    const EVP_MD *md = NULL;
+    int padByteOffset = 25 * sizeof(uint64_t) + 3 * sizeof(size_t) + 1600/8 - 32;
+    CHECKED(md = EVP_sha3_512());
+    CHECKED(EVP_DigestInit(ctx, md));
+
+    // MAGIC (set padding char to 0x1)
+    ((uint8_t *) EVP_MD_CTX_md_data(ctx))[padByteOffset] = 0x01;
+finally:
+    return ok;
+}
+
 int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l)
 {
     return EVP_DigestUpdate(ctx, p, l);
 }
 
+int keccak512_update(KECCAK512_CTX *ctx, const void *p, size_t l)
+{
+    return EVP_DigestUpdate(ctx, p, l);
+}
+
 int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md)
 {
     unsigned int l;
     return EVP_DigestFinal(ctx, md, &l);
 }
 
+int keccak512_final(KECCAK512_CTX *ctx, unsigned char *md)
+{
+    unsigned int l;
+    return EVP_DigestFinal(ctx, md, &l);
+}
+
 void keccak256_freectx(KECCAK256_CTX *ctx)
+{
+    return EVP_MD_CTX_free(ctx);
+}
+
+void keccak512_freectx(KECCAK512_CTX *ctx)
 {
     return EVP_MD_CTX_free(ctx);
 }
diff --git a/cbits/keccak.h b/cbits/keccak.h
--- a/cbits/keccak.h
+++ b/cbits/keccak.h
@@ -16,15 +16,25 @@
 #elif OPENSSL_VERSION_NUMBER >= 0x30000000L
 typedef struct keccak1600_ctx_st KECCAK1600_CTX;
 typedef KECCAK1600_CTX KECCAK256_CTX;
+typedef KECCAK1600_CTX KECCAK512_CTX;
 
 #elif OPENSSL_VERSION_NUMBER >= 0x10100000L
 typedef EVP_MD_CTX KECCAK256_CTX;
+typedef EVP_MD_CTX KECCAK512_CTX;
 
 #endif
 
+// KECCAK-256
 KECCAK256_CTX *keccak256_newctx();
 int keccak256_init(KECCAK256_CTX *ctx);
 int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l);
 int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md);
 void keccak256_freectx(KECCAK256_CTX *ctx);
+
+// KECCAK-512
+KECCAK512_CTX *keccak512_newctx();
+int keccak512_init(KECCAK512_CTX *ctx);
+int keccak512_update(KECCAK512_CTX *ctx, const void *p, size_t l);
+int keccak512_final(KECCAK512_CTX *ctx, unsigned char *md);
+void keccak512_freectx(KECCAK512_CTX *ctx);
 
diff --git a/hashes.cabal b/hashes.cabal
--- a/hashes.cabal
+++ b/hashes.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.4
 name: hashes
-version: 0.2.0.0
+version: 0.2.1.0
 synopsis: Hash functions
 Description: Efficient implementations of hash functions
 homepage: https://github.com/larskuhtz/hs-hashes
diff --git a/src/Data/Hash/Internal/OpenSSL.hs b/src/Data/Hash/Internal/OpenSSL.hs
--- a/src/Data/Hash/Internal/OpenSSL.hs
+++ b/src/Data/Hash/Internal/OpenSSL.hs
@@ -65,6 +65,7 @@
 -- $keccak
 
 , Keccak256(..)
+, Keccak512(..)
 
 -- ** Blake2
 --
@@ -365,6 +366,8 @@
 --
 -- For details see the file cbits/keccak.c.
 
+-- KECCAK-256
+
 newtype Keccak256 = Keccak256 BS.ShortByteString
     deriving (Eq, Ord)
     deriving (Show) via B16ShortByteString
@@ -410,6 +413,57 @@
         Ctx ctx <- newKeccak256Ctx
         r <- withForeignPtr ctx $ \ptr ->
             c_keccak256_init ptr
+        unless r $ throw $ OpenSslException "digest initialization failed"
+        return $ Ctx ctx
+    {-# INLINE initialize #-}
+
+-- KECCAK-512
+
+newtype Keccak512 = Keccak512 BS.ShortByteString
+    deriving (Eq, Ord)
+    deriving (Show) via B16ShortByteString
+
+foreign import ccall unsafe "keccak.h keccak512_newctx"
+    c_keccak512_newctx :: IO (Ptr ctx)
+
+foreign import ccall unsafe "keccak.h keccak512_init"
+    c_keccak512_init :: Ptr ctx -> IO Bool
+
+foreign import ccall unsafe "keccak.h keccak512_update"
+    c_keccak512_update :: Ptr ctx -> Ptr Word8 -> Int -> IO Bool
+
+foreign import ccall unsafe "keccak.h keccak512_final"
+    c_keccak512_final :: Ptr ctx -> Ptr Word8 -> IO Bool
+
+foreign import ccall unsafe "keccak.h &keccak512_freectx"
+    c_keccak512_freectx_ptr :: FunPtr (Ptr ctx -> IO ())
+
+instance IncrementalHash Keccak512 where
+    type Context Keccak512 = Ctx Keccak512
+    update (Ctx ctx) ptr n = withForeignPtr ctx $ \cptr -> do
+        r <- c_keccak512_update cptr ptr n
+        unless r $ throw $ OpenSslException "digest update failed"
+    finalize (Ctx ctx) = withForeignPtr ctx $ \cptr -> do
+        allocaBytes 64 $ \dptr -> do
+            r <- c_keccak512_final cptr dptr
+            unless r $ throw $ OpenSslException "digest finalization failed"
+            Keccak512 <$> BS.packCStringLen (castPtr dptr, 64)
+    {-# INLINE update #-}
+    {-# INLINE finalize #-}
+
+
+newKeccak512Ctx :: IO (Ctx Keccak512)
+newKeccak512Ctx = fmap Ctx $ mask_ $ do
+    ptr <- c_keccak512_newctx
+    when (ptr == nullPtr) $ throw $ OpenSslException "failed to initialize context"
+    newForeignPtr c_keccak512_freectx_ptr ptr
+{-# INLINE newKeccak512Ctx #-}
+
+instance Hash Keccak512 where
+    initialize = do
+        Ctx ctx <- newKeccak512Ctx
+        r <- withForeignPtr ctx $ \ptr ->
+            c_keccak512_init ptr
         unless r $ throw $ OpenSslException "digest initialization failed"
         return $ Ctx ctx
     {-# INLINE initialize #-}
diff --git a/src/Data/Hash/Keccak.hs b/src/Data/Hash/Keccak.hs
--- a/src/Data/Hash/Keccak.hs
+++ b/src/Data/Hash/Keccak.hs
@@ -31,6 +31,7 @@
 -- This version of Keccak-256 is used by the Ethereum project.
 
   Keccak256(..)
+, Keccak512(..)
 , module Data.Hash.Class.Mutable
 ) where
 
diff --git a/test/Cryptonite.hs b/test/Cryptonite.hs
--- a/test/Cryptonite.hs
+++ b/test/Cryptonite.hs
@@ -161,6 +161,7 @@
     , ("Blake2s256", property $ prop_eq @Blake2s256 @C.Blake2s_256)
     , ("Blake2b512", property $ prop_eq @Blake2b512 @C.Blake2b_512)
     , ("Keccak256", property $ prop_eq @Keccak256 @C.Keccak_256)
+    , ("Keccak512", property $ prop_eq @Keccak512 @C.Keccak_512)
 #endif
     ]
 
