libsodium-bindings-0.0.1.0: src/LibSodium/Bindings/Utils.hs
{-# 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