libsodium 1.0.18.0 → 1.0.18.1
raw patch · 4 files changed
+152/−13 lines, 4 files
Files
- CHANGELOG.md +5/−0
- lib/Libsodium.chs +109/−12
- libsodium.cabal +1/−1
- test/Main.chs +37/−0
CHANGELOG.md view
@@ -1,3 +1,8 @@+# Version 1.0.18.1++* Improve support for opaque C structs (`Storable`, `Ptr`, allocation).++ # Version 1.0.18.0 * Initial version.
lib/Libsodium.chs view
@@ -1,10 +1,13 @@+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -Wno-missing-signatures #-} #include <sodium.h> @@ -334,19 +337,39 @@ -- -- $types , Crypto_aead_aes256gcm_state+ , crypto_aead_aes256gcm_state'ptr+ , crypto_aead_aes256gcm_state'malloc , Crypto_auth_hmacsha256_state+ , crypto_auth_hmacsha256_state'ptr+ , crypto_auth_hmacsha256_state'malloc+ , Crypto_auth_hmacsha512256_state , Crypto_auth_hmacsha512_state+ , crypto_auth_hmacsha512_state'ptr+ , crypto_auth_hmacsha512_state'malloc , Crypto_generichash_blake2b_state+ , crypto_generichash_blake2b_state'ptr+ , crypto_generichash_blake2b_state'malloc+ , Crypto_generichash_state , Crypto_hash_sha256_state+ , crypto_hash_sha256_state'ptr+ , crypto_hash_sha256_state'malloc , Crypto_hash_sha512_state+ , crypto_hash_sha512_state'ptr+ , crypto_hash_sha512_state'malloc , Crypto_onetimeauth_poly1305_state+ , crypto_onetimeauth_poly1305_state'ptr+ , crypto_onetimeauth_poly1305_state'malloc+ , Crypto_onetimeauth_state , Crypto_secretstream_xchacha20poly1305_state+ , crypto_secretstream_xchacha20poly1305_state'ptr+ , crypto_secretstream_xchacha20poly1305_state'malloc , Crypto_sign_ed25519ph_state- , Crypto_auth_hmacsha512256_state- , Crypto_generichash_state- , Crypto_onetimeauth_state+ , crypto_sign_ed25519ph_state'ptr+ , crypto_sign_ed25519ph_state'malloc , Crypto_sign_state , Randombytes_implementation+ , randombytes_implementation'ptr+ , randombytes_implementation'malloc -- * Constants -- -- $constants@@ -354,9 +377,12 @@ ) --} where +import Data.Coerce import Data.Proxy import Data.Word import Foreign.C+import Foreign.ForeignPtr+import Foreign.Marshal.Array (copyArray) import Foreign.Ptr import Foreign.Storable import GHC.TypeLits@@ -782,15 +808,33 @@ -------------------------------------------------------------------------------- -- $types ----- These are types used by some of the functions in--- "Libsodium". They are exported as opaque types.+-- These are types used by some of the functions in "Libsodium".+-- They are exported as opaque types having a particular size and+-- alignment described by their 'Storable' instance. ----- Use 'Storable' if you need to allocate values of these types.--newtype Crypto_aead_aes256gcm_state = Crypto_aead_aes256gcm_state- (Opaque 16 {# sizeof crypto_aead_aes256gcm_state #})+-- Use the @/xxx/'malloc@ functions to allocate values of type @Xxx@. These+-- will be freed from memory as soon as they become unused.+--+-- Use the @/xxx/'ptr@ function to obtain a+-- @'Ptr' Xxx@ suitable for passing to functions.+newtype Crypto_aead_aes256gcm_state+ = Crypto_aead_aes256gcm_state+ (Opaque 16 {# sizeof crypto_aead_aes256gcm_state #}) deriving newtype (Storable) +crypto_aead_aes256gcm_state'malloc+ :: IO Crypto_aead_aes256gcm_state+crypto_aead_aes256gcm_state'malloc =+ fmap Crypto_aead_aes256gcm_state opaque'malloc++crypto_aead_aes256gcm_state'ptr+ :: Crypto_aead_aes256gcm_state+ -> (Ptr Crypto_aead_aes256gcm_state -> IO x)+ -> IO x+crypto_aead_aes256gcm_state'ptr = opaque'ptr+ @Crypto_aead_aes256gcm_state++--- type Crypto_sign_state = Crypto_sign_ed25519ph_state newtype Crypto_sign_ed25519ph_state = Crypto_sign_ed25519ph_state@@ -798,34 +842,58 @@ {# sizeof crypto_sign_ed25519ph_state #}) deriving newtype (Storable) +crypto_sign_ed25519ph_state'ptr = opaque'ptr @Crypto_sign_ed25519ph_state+crypto_sign_ed25519ph_state'malloc = fmap Crypto_sign_ed25519ph_state opaque'malloc++--- newtype Crypto_secretstream_xchacha20poly1305_state = Crypto_secretstream_xchacha20poly1305_state (Opaque {# alignof crypto_secretstream_xchacha20poly1305_state #} {# sizeof crypto_secretstream_xchacha20poly1305_state #}) deriving newtype (Storable) +crypto_secretstream_xchacha20poly1305_state'ptr = opaque'ptr @Crypto_secretstream_xchacha20poly1305_state+crypto_secretstream_xchacha20poly1305_state'malloc = fmap Crypto_secretstream_xchacha20poly1305_state opaque'malloc++--- type Crypto_onetimeauth_state = Crypto_onetimeauth_poly1305_state newtype Crypto_onetimeauth_poly1305_state = Crypto_onetimeauth_poly1305_state (Opaque 16 {# sizeof crypto_onetimeauth_poly1305_state #}) deriving newtype (Storable) +crypto_onetimeauth_poly1305_state'ptr = opaque'ptr @Crypto_onetimeauth_poly1305_state+crypto_onetimeauth_poly1305_state'malloc = fmap Crypto_onetimeauth_poly1305_state opaque'malloc++--- type Crypto_generichash_state = Crypto_generichash_blake2b_state newtype Crypto_generichash_blake2b_state = Crypto_generichash_blake2b_state (Opaque 64 {# sizeof crypto_generichash_blake2b_state #}) deriving newtype (Storable) +crypto_generichash_blake2b_state'ptr = opaque'ptr @Crypto_generichash_blake2b_state+crypto_generichash_blake2b_state'malloc = fmap Crypto_generichash_blake2b_state opaque'malloc++--- newtype Crypto_hash_sha256_state = Crypto_hash_sha256_state (Opaque {# alignof crypto_hash_sha256_state #} {# sizeof crypto_hash_sha256_state #}) deriving newtype (Storable) +crypto_hash_sha256_state'ptr = opaque'ptr @Crypto_hash_sha256_state+crypto_hash_sha256_state'malloc = fmap Crypto_hash_sha256_state opaque'malloc++--- newtype Crypto_hash_sha512_state = Crypto_hash_sha512_state (Opaque {# alignof crypto_hash_sha512_state #} {# sizeof crypto_hash_sha512_state #}) deriving newtype (Storable) +crypto_hash_sha512_state'ptr = opaque'ptr @Crypto_hash_sha512_state+crypto_hash_sha512_state'malloc = fmap Crypto_hash_sha512_state opaque'malloc++--- type Crypto_auth_hmacsha512256_state = Crypto_auth_hmacsha512_state newtype Crypto_auth_hmacsha512_state = Crypto_auth_hmacsha512_state@@ -833,25 +901,54 @@ {# sizeof crypto_auth_hmacsha512_state #}) deriving newtype (Storable) +crypto_auth_hmacsha512_state'ptr = opaque'ptr @Crypto_auth_hmacsha512_state+crypto_auth_hmacsha512_state'malloc = fmap Crypto_auth_hmacsha512_state opaque'malloc++--- newtype Crypto_auth_hmacsha256_state = Crypto_auth_hmacsha256_state (Opaque {# alignof crypto_auth_hmacsha256_state #} {# sizeof crypto_auth_hmacsha256_state #}) deriving newtype (Storable) +crypto_auth_hmacsha256_state'ptr = opaque'ptr @Crypto_auth_hmacsha256_state+crypto_auth_hmacsha256_state'malloc = fmap Crypto_auth_hmacsha256_state opaque'malloc++--- newtype Randombytes_implementation = Randombytes_implementation (Opaque {# alignof randombytes_implementation #} {# sizeof randombytes_implementation #}) deriving newtype (Storable) +randombytes_implementation'ptr = opaque'ptr @Randombytes_implementation+randombytes_implementation'malloc = fmap Randombytes_implementation opaque'malloc+ -------------------------------------------------------------------------------- -newtype Opaque (alignment :: Nat) (size :: Nat) = Opaque (Ptr ())+newtype Opaque (alignment :: Nat) (size :: Nat)+ = Opaque (ForeignPtr (Opaque alignment size)) instance forall a s. (KnownNat a, KnownNat s) => Storable (Opaque a s) where alignment _ = fromIntegral (natVal (Proxy :: Proxy a)) sizeOf _ = fromIntegral (natVal (Proxy :: Proxy s))- peek z = Opaque <$> peek (castPtr z)- poke z (Opaque a) = poke (castPtr z) a+ peek ps = do+ fpd <- mallocForeignPtr+ withForeignPtr fpd $ \pd -> copyArray pd ps 1+ pure $ Opaque fpd+ poke pd (Opaque fps) =+ withForeignPtr fps $ \ps -> copyArray pd ps 1++opaque'malloc :: (KnownNat a, KnownNat s) => IO (Opaque a s)+opaque'malloc = fmap Opaque mallocForeignPtr++opaque'ptr+ :: forall o a s x+ . Coercible o (Opaque a s)+ => o+ -> (Ptr o -> IO x)+ -> IO x+opaque'ptr o g =+ let Opaque fp = coerce o :: Opaque a s+ in withForeignPtr fp (g . castPtr) -------------------------------------------------------------------------------- -- $constants
libsodium.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: libsodium-version: 1.0.18.0+version: 1.0.18.1 license: ISC license-file: LICENSE extra-source-files: README.md CHANGELOG.md
test/Main.chs view
@@ -1,3 +1,5 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-} #include <sodium.h> module Main (main) where@@ -6,6 +8,8 @@ import Control.Monad.IO.Class import Foreign.C.String import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Storable import qualified Test.Tasty as Tasty import qualified Test.Tasty.Runners as Tasty import Test.Tasty (TestTree, testGroup)@@ -68,6 +72,39 @@ [ tt_core , tt_constants , tt_randombytes+ , tt_storable+ ]++tt_storable :: TestTree+tt_storable = testGroup "Storable"+ [ testCase "alloc" $ do+ _ :: ForeignPtr L.Crypto_hash_sha256_state <- mallocForeignPtr+ pure ()++ , testCase "peek" $ do+ -- Allocate s1 and fill with random bytes+ s1 <- L.crypto_hash_sha256_state'malloc+ L.crypto_hash_sha256_state'ptr s1 $ \p1 -> do+ L.randombytes_buf p1 (fromIntegral (sizeOf s1))+ -- Allocate s2 by peeking from s1+ s2 <- peek p1+ L.crypto_hash_sha256_state'ptr s2 $ \p2 -> do+ -- Compare s1 and s2+ x <- L.sodium_memcmp p1 p2 (fromIntegral (sizeOf s1))+ 0 @=? x++ , testCase "poke" $ do+ -- Allocate s1 and fill with random bytes+ s1 <- L.crypto_hash_sha256_state'malloc+ L.crypto_hash_sha256_state'ptr s1 $ \p1 -> do+ L.randombytes_buf p1 (fromIntegral (sizeOf s1))+ -- Allocate s2 and poke s1 into it+ s2 <- L.crypto_hash_sha256_state'malloc+ L.crypto_hash_sha256_state'ptr s2 $ \p2 -> do+ poke p2 s1+ -- Compare s1 and s2+ x <- L.sodium_memcmp p1 p2 (fromIntegral (sizeOf s1))+ 0 @=? x ] tt_core :: TestTree