-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add initial bindings to hashing algorithms, and add code style #1
Conversation
84c1d33
to
ca4f755
Compare
src/Cryptography/LibSodium/FFI.hsc
Outdated
-- | @int sodium_compare(const void * const b1_, const void * const b2_, size_t len);@ | ||
-- | ||
-- <https://libsodium.gitbook.io/doc/helpers#comparing-large-numbers> | ||
foreign import capi unsafe "sodium.h sodium_compare" c_sodium_compare :: Ptr a -> Ptr a -> CSize -> IO CInt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put that in its own module
src/Cryptography/LibSodium/FFI.hsc
Outdated
-- From https://libsodium.gitbook.io/doc/advanced/sha-2_hash_function | ||
-- and https://libsodium.gitbook.io/doc/hashing/generic_hashing | ||
|
||
type CRYPTO_SHA256_BYTES = #{const crypto_hash_sha256_BYTES} | ||
type CRYPTO_SHA512_BYTES = #{const crypto_hash_sha512_BYTES} | ||
type CRYPTO_BLAKE2B_256_BYTES = #{const crypto_generichash_blake2b_BYTES} | ||
|
||
type CRYPTO_SHA256_STATE_SIZE = #{size crypto_hash_sha256_state} | ||
type CRYPTO_SHA512_STATE_SIZE = #{size crypto_hash_sha512_state} | ||
type CRYPTO_BLAKE2B_256_STATE_SIZE = #{size crypto_generichash_blake2b_state} | ||
|
||
type CRYPTO_SIGN_ED25519_BYTES = #{const crypto_sign_ed25519_BYTES} | ||
type CRYPTO_SIGN_ED25519_SEEDBYTES = #{const crypto_sign_ed25519_SEEDBYTES} | ||
type CRYPTO_SIGN_ED25519_PUBLICKEYBYTES = #{const crypto_sign_ed25519_PUBLICKEYBYTES} | ||
type CRYPTO_SIGN_ED25519_SECRETKEYBYTES = #{const crypto_sign_ed25519_SECRETKEYBYTES} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything goes
src/Cryptography/LibSodium/Utils.hs
Outdated
|
||
-- A pointer which knows the size of underlying memory block | ||
newtype SizedPtr (n :: Nat) = SizedPtr (Ptr Void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Irrelevant
src/Cryptography/LibSodium/Utils.hs
Outdated
|
||
-- | Like 'allocaBytes'. | ||
allocaSized :: forall n b. KnownNat n => (SizedPtr n -> IO b) -> IO b | ||
allocaSized k = allocaBytes (fromCInt size) (k . SizedPtr) | ||
where | ||
size :: CInt | ||
size = fromInteger (natVal (Proxy @n)) | ||
|
||
memcpySized :: forall n. KnownNat n => SizedPtr n -> SizedPtr n -> IO () | ||
memcpySized (SizedPtr dest) (SizedPtr src) = void (c_memcpy dest src size) | ||
where | ||
size :: CSize | ||
size = fromInteger (natVal (Proxy @n)) | ||
|
||
memsetSized :: forall n. KnownNat n => SizedPtr n -> Word8 -> IO () | ||
memsetSized (SizedPtr s) c = void (c_memset s (fromIntegral c) size) | ||
where | ||
size :: CSize | ||
size = fromInteger (natVal (Proxy @n)) | ||
|
||
fromCInt :: CInt -> Int | ||
fromCInt = fromIntegral |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That can go away
src/Cryptography/LibSodium/Utils.hs
Outdated
|
||
------------------------------------------------------------------------------- | ||
-- Some C functions | ||
------------------------------------------------------------------------------- | ||
|
||
-- | @void *memcpy(void *dest, const void *src, size_t n);@ | ||
-- | ||
-- Note: this is safe foreign import | ||
foreign import ccall "memcpy" | ||
c_memcpy :: Ptr a -> Ptr a -> CSize -> IO (Ptr ()) | ||
|
||
-- | @void *memset(void *s, int c, size_t n);@ | ||
-- | ||
-- Note: for sure zeroing memory use @c_sodium_memzero@. | ||
foreign import ccall "memset" | ||
c_memset :: Ptr a -> CInt -> CSize -> IO (Ptr ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That goes away
src/Cryptography/LibSodium/FFI.hsc
Outdated
foreign import capi unsafe "sodium.h crypto_hash_sha256" c_crypto_hash_sha256 :: SizedPtr CRYPTO_SHA256_BYTES -> Ptr CUChar -> CULLong -> IO CInt | ||
|
||
-- | @int crypto_hash_sha256_init(crypto_hash_sha256_state *state);@ | ||
foreign import capi unsafe "sodium.h crypto_hash_sha256_init" c_crypto_hash_sha256_init :: SizedPtr CRYPTO_SHA256_STATE_SIZE -> IO CInt | ||
|
||
-- | @int crypto_hash_sha256_update(crypto_hash_sha256_state *state, const unsigned char *in, unsigned long long inlen);@ | ||
foreign import capi unsafe "sodium.h crypto_hash_sha256_update" c_crypto_hash_sha256_update :: SizedPtr CRYPTO_SHA256_STATE_SIZE -> Ptr CUChar -> CULLong -> IO CInt | ||
|
||
-- | @int crypto_hash_sha256_final(crypto_hash_sha256_state *state, unsigned char *out);@ | ||
foreign import capi unsafe "sodium.h crypto_hash_sha256_final" c_crypto_hash_sha256_final :: SizedPtr CRYPTO_SHA256_STATE_SIZE -> SizedPtr CRYPTO_SHA256_BYTES -> IO CInt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the real C types instead of SizedPtr
src/Cryptography/LibSodium/FFI.hsc
Outdated
foreign import capi unsafe "sodium.h crypto_generichash_blake2b" c_crypto_generichash_blake2b | ||
:: Ptr out -> CSize | ||
-> Ptr CUChar -> CULLong | ||
-> Ptr key -> CSize | ||
-> IO CInt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document each parameter and their relation.
src/Cryptography/LibSodium/FFI.hsc
Outdated
-- | @int crypto_generichash_blake2b(unsigned char *out, size_t outlen, const unsigned char *in, unsigned long long inlen, const unsigned char *key, size_t keylen);@ | ||
-- | ||
-- <https://libsodium.gitbook.io/doc/hashing/generic_hashing> | ||
foreign import capi unsafe "sodium.h crypto_generichash_blake2b" c_crypto_generichash_blake2b |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Out parameter, this is where the result of the hash will go
- Length of the result
- In parameter ,what you want to hash
- Length of what you want to hash
- Key
- Length of the key
3e2d8e5
to
174d2d0
Compare
So, I'm a little worried here because:
typedef struct crypto_sign_ed25519ph_state {
crypto_hash_sha512_state hs;
} crypto_sign_ed25519ph_state;
@jmcardon Am I missing anything? Does that mean we should provide signing from another backend? |
fcdfb75
to
43f4e7a
Compare
b722e5d
to
92eb677
Compare
#define SODIUM_VERSION_STRING "1.0.18" | ||
|
||
#define SODIUM_LIBRARY_VERSION_MAJOR 10 | ||
#define SODIUM_LIBRARY_VERSION_MINOR 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these correspond to each other?
-- <https://libsodium.gitbook.io/doc/usage> | ||
-- | ||
-- @since 0.0.1.0 | ||
foreign import capi "sodium.h sodium_init" c_sodium_init :: IO CInt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we ensure that users of the library call this? it would be nice to make sure it's run when the program starts without having to remember to do anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that's the easiest way. You can (and indeed, should) also document that c_sodium_init
must be called before any other functionality is used for those who don't want to use secureMain
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
-> IO CInt | ||
|
||
-- | @int crypto_generichash_blake2b_update(crypto_generichash_blake2b_state *state, const unsigned char *in, unsigned long long inlen)@ | ||
foreign import capi unsafe "sodium.h crypto_generichash_blake2b_update" c_crypto_generichash_blake2b_update |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's hard to tell if these should be safe or unsafe, it feels like for small inputs unsafe would be fine, but if someone mmaps a 4TB file and hashes it, this is going to be problematic. I'd thought about exposing both and then on the Haskell side choosing based on the data size. Whether the runtime of hashing algorithms has security concerns I have no idea...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good thinking
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say this is a case of 'offer both options, explain why they're different' for sure. Automagical deciding could be done at a higher level, but even then, I'm not sure if it's a good idea.
go outPtr arrPtr = traverse_ | ||
(\i -> peek @CUChar (plusPtr arrPtr i) >>= poke (plusPtr outPtr i)) [0..383] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance this could be a memcpy? https://hackage.haskell.org/package/base-4.16.0.0/docs/Foreign-Marshal-Utils.html#v:copyBytes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I'd rather generate those with c2hs, these are not here to stay. :)
instance Ix CSize where | ||
range (CSize m, CSize n) = CSize <$> range (m, n) | ||
unsafeIndex (CSize m, CSize n) (CSize i) = unsafeIndex (m, n) i | ||
inRange (CSize m, CSize n) (CSize i) = inRange (m, n) i |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be a useful thing to get added to base
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't say: https://gitlab.haskell.org/ghc/ghc/-/issues/20934
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm honestly surprised these don't exist already.
This PR brings:
Dependencies
Data.Ix.Ix
instances for theForeign.C.Type
newtypes haskell/core-libraries-committee#30