{-# LANGUAGE CApiFFI #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE Trustworthy #-} {-# OPTIONS_GHC -Wno-unused-imports #-} -- | -- Module: LibSodium.Bindings.Utils -- Description: Helpers exposed by the libsodium C library -- Copyright: (C) Seth Livy 2022 -- License: BSD-3-Clause -- Maintainer: The Haskell Cryptography Group -- Stability: Stable -- Portability: GHC only -- -- These are bindings to some of libsodium's [utils.h](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/utils.h). -- Included are Hex and Base64 encoding/decoding functions along with a constant-time @memcmp@ for handling secret data. module LibSodium.Bindings.Utils ( -- * Low-level binding sodiumMemcmp , sodiumBin2Hex -- , sodiumHex2Bin , sodiumBin2Base64 -- , sodiumBase642Bin -- * Constants , sodiumBase64VariantOriginal , sodiumBase64VariantOriginalNoPadding , sodiumBase64VariantURLSafe , sodiumBase64VariantURLSafeNoPadding ) where import Foreign (Ptr) import Foreign.C (CChar (..), CInt (..), CSize (..), CUChar (..)) import Foreign.C.String -- | Constant-time comparison function. -- -- This function is not a lexicographic comparator and should be never -- used for this purpose. It should only be used when comparing two pieces -- of secret data, such as keys or authentication tags. -- -- @since 0.0.1.0 foreign import capi "sodium.h sodium_memcmp" sodiumMemcmp :: Ptr CUChar -- ^ First pointer to some secret data. -> Ptr CUChar -- ^ Second pointer to some secret data. -- Must be the same length as the first pointer. -> CSize -- ^ The length of bytes that pointed to by both previous arguments. -> IO CInt -- ^ 0 if successful, -1 on failure. -- | Encode bytes to a hexidecimal string. Constant-time. -- -- @since 0.0.1.0 foreign import capi "sodium.h sodium_bin2hex" sodiumBin2Hex :: CString -- ^ @hex@, The output buffer. -> CSize -- ^ @hex_len@, The maximum number of bytes this function is allowed to write -- to the output buffer. Must be at least @bin_len * 2 + 1@ bytes long. -> Ptr CUChar -- ^ @bin@, The input buffer. -> CSize -- ^ @bin_len@, The length of the input buffer. -> IO CString -- ^ The return string, terminated with a null byte. {- Due to a deficiency in Haskell's C FFI regarding nested pointers, this function and its Base64 counterpart have been commented out. The C shim that GHC generates ignores the @const@ qualifier in the type for @hex_end@, leading to multiple type errors. There is a pull request in GHC to fix this that is to ship with GHC 9.6. https://gitlab.haskell.org/ghc/ghc/-/commit/4f70a8a0b5db49ff249271faefec14bf1421f365 -} {- -- | Decode a hexadecimal string to bytes. Constant-time. foreign import capi "sodium.h sodium_hex2bin" sodiumHex2Bin :: Ptr CUChar -- ^ @bin@, The output buffer. -> CSize -- ^ @bin_maxlen@, The maximum length of the output buffer. -> CString -- ^ @hex@, The input string. -> CSize -- ^ @hex_len@, The length of the input. -> CString -- ^ @ignore@, a string of characters for the parser to skip. -- For example, the string ": " allows colons and spaces in the input. -- These characters will ignored and will not be present in the output. -> Ptr CSize -- ^ @bin_len@, The length of the output buffer. -> Ptr CString -- ^ @hex_end@, A pointer to the end of the input string. -- If this isn't null, then it will be set to the first byte after the last -- valid parsed character. -> IO CInt -- ^ 0 if successful, -1 on failure. Common failures are if the string -- couldn't be fully parsed or if the parsed string is longer than the -- maximum amount of bytes allocated to store it. -} -- | Encode bytes to a Base64 string. Constant-time. foreign import capi "sodium.h sodium_bin2base64" sodiumBin2Base64 :: CString -- ^ @b64@, The output buffer. -> CSize -- ^ @b64_maxlen@, The maximum length of the output buffer. -- Choosing a correct size is not straightforward and depends on -- the variant. The @sodium_base64_ENCODED_LEN(BIN_LEN, VARIANT)@ -- macro computes the minimum amount of bytes needed to encode BIN_LEN -- bytes with a chosen VARIANT. -> Ptr CUChar -- ^ @bin@, The input buffer. -> CSize -- ^ @bin_len@, The length of the input buffer. -> CInt -- ^ @variant@, Which Base64 variant to use. None of the variants provide -- any encryption. -> IO CString -- ^ The returned Base64 string, terminated with a null byte. {- foreign import capi "sodium.h sodium_base642bin" sodiumBase642Bin :: Ptr CUChar -- ^ @bin@, The output buffer. -> CSize -- ^ @bin_maxlen@, The maximum length of the output buffer. -> CString -- ^ @b64@, The input string. -> CSize -- ^ @b64_len@, The length of the input. -> CString -- ^ @ignore@, a string of characters for the parser to skip. -- For example, the string ": " allows colons and spaces in the input. -- These characters will ignored and will not be present in the output. -> Ptr CSize -- ^ @bin_len@, The length of the output buffer. -- This will always be at most @b64_len / 4 * 3@ bytes long. -> Ptr CString -- ^ @b64_end@, A pointer to the end of the input string. -- If this isn't null, then it will be set to the first byte after the last -- valid parsed character. -> CInt -- ^ @variant@, Which Base64 variant to use. None of the variants provide -- any encryption. -> IO CInt -- ^ 0 if successful, -1 on failure. Common failures are if the string -- couldn't be fully parsed or if the parsed string is longer than the -- maximum amount of bytes allocated to store it. -} -- | The original variant of Base64 with padding. This ensures that the -- length of the encoded data will always be a multiple of four bytes. foreign import capi "sodium.h value sodium_base64_VARIANT_ORIGINAL" sodiumBase64VariantOriginal :: CInt -- | The original variant of Base64. No variant offers any security advantages -- over the other. foreign import capi "sodium.h value sodium_base64_VARIANT_ORIGINAL_NO_PADDING" sodiumBase64VariantOriginalNoPadding :: CInt -- | The URL-safe variant of Base64 with padding. foreign import capi "sodium.h value sodium_base64_VARIANT_URLSAFE" sodiumBase64VariantURLSafe :: CInt -- | The URL-safe variant of Base64. This is the same as the original variant, -- except '+' and '/' are replaced with '-' and '_'. foreign import capi "sodium.h value sodium_base64_VARIANT_URLSAFE_NO_PADDING" sodiumBase64VariantURLSafeNoPadding :: CInt