packages feed

Z-Botan 0.3.0.0 → 0.3.1.0

raw patch · 7 files changed

+70/−29 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Z.Botan.FFI: botan_cipher_get_minimum_final_size :: BotanStructT -> MBA# Int -> IO CInt

Files

ChangeLog.md view
@@ -1,6 +1,10 @@ # Revision history for z-botan -## 0.2.0.0  -- 2020-05-14+## 0.3.1.0  -- 2020-05-14++* Change `cipherBIO` to buffer an extra chunk so that the last chunk is larger than minimum final chunk size, add a file encryption example.++## 0.3.0.0  -- 2020-05-14  * Change `EMEPadding` to `EncParam`, add `SM2EncParam`. * Change `EMSA` to `SignParam`, add `Ed25519Pure`, `Ed25519ph`, `Ed25519Hash`, `SM2SignParam`.
Z-Botan.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               Z-Botan-version:            0.3.0.0+version:            0.3.1.0 synopsis:           Crypto for Haskell description:        Crypto for Haskell, based on <http://botan.randombit.net/ Botan> license:            BSD-3-Clause
Z/Botan/FFI.hsc view
@@ -218,6 +218,7 @@ foreign import ccall unsafe botan_cipher_get_default_nonce_length :: BotanStructT -> MBA## Int -> IO CInt foreign import ccall unsafe botan_cipher_get_update_granularity :: BotanStructT -> MBA## Int -> IO CInt foreign import ccall unsafe botan_cipher_get_tag_length :: BotanStructT -> MBA## Int -> IO CInt+foreign import ccall unsafe botan_cipher_get_minimum_final_size :: BotanStructT -> MBA## Int -> IO CInt  -------------------------------------------------------------------------------- -- PBKDF
Z/Crypto/Cipher.hs view
@@ -387,10 +387,13 @@         (t, _) <- allocPrimUnsafe $ \ pt ->             botan_cipher_get_tag_length pci pt +        (f, _) <- allocPrimUnsafe $ \ pt ->+            botan_cipher_get_minimum_final_size pci pt+         (n, _) <- allocPrimUnsafe $ \ pn ->             botan_cipher_get_default_nonce_length pci pn -        return (Cipher ci name g (KeySpec a b c) t n)+        return (Cipher ci name g (KeySpec a b c) t f n)  -------------------------------------------------------------------------------- --@@ -538,7 +541,8 @@     , cipherKeySpec           :: {-# UNPACK #-} !KeySpec       -- ^ cipher keyspec     , cipherTagLength         :: {-# UNPACK #-} !Int    -- ^ AEAD tag length,                                                         -- will be zero for non-authenticated ciphers.-    , defaultNonceLength      :: {-# UNPACK #-} !Int    -- ^ a proper default nonce length+    , cipherMinFinalSize      :: {-# UNPACK #-} !Int    -- ^ Minimum input size for final chunk.+    , defaultNonceLength      :: {-# UNPACK #-} !Int    -- ^ a proper default nonce length.     }     deriving (Show, Generic)     deriving anyclass T.Print@@ -546,7 +550,7 @@ -- | Pass 'Cipher' to FFI as 'botan_cipher_t'. withCipher :: Cipher -> (BotanStructT -> IO r) -> IO r {-# INLINABLE withCipher #-}-withCipher (Cipher c _ _ _ _ _) = withBotanStruct c+withCipher (Cipher c _ _ _ _ _ _) = withBotanStruct c  -- | Create a new cipher. --@@ -572,17 +576,20 @@         (t, _) <- allocPrimUnsafe $ \ pt ->             botan_cipher_get_tag_length pci pt +        (f, _) <- allocPrimUnsafe $ \ pt ->+            botan_cipher_get_minimum_final_size pci pt+         (n, _) <- allocPrimUnsafe $ \ pn ->             botan_cipher_get_default_nonce_length pci pn -        return (Cipher ci name g (KeySpec a b c) t n)+        return (Cipher ci name g (KeySpec a b c) t f n)  -- | Clear the internal state (such as keys) of this cipher object. -- clearCipher :: HasCallStack => Cipher -> IO () {-# INLINABLE clearCipher #-}-clearCipher (Cipher ci _ _ _ _ _) =-    withBotanStruct ci (throwBotanIfMinus_ . botan_cipher_clear)+clearCipher ci =+    withCipher ci (throwBotanIfMinus_ . botan_cipher_clear)  -- | Reset the message specific state for this cipher. -- Without resetting the keys, this resets the nonce, and any state@@ -593,15 +600,15 @@ -- resetCipher :: HasCallStack => Cipher -> IO () {-# INLINABLE resetCipher #-}-resetCipher (Cipher ci _ _ _ _ _) =-    withBotanStruct ci (throwBotanIfMinus_ . botan_cipher_reset)+resetCipher ci =+    withCipher ci (throwBotanIfMinus_ . botan_cipher_reset)  -- | Set the key for this cipher object -- setCipherKey :: HasCallStack => Cipher -> V.Bytes -> IO () {-# INLINABLE setCipherKey #-}-setCipherKey (Cipher ci _ _ _ _ _) key =-    withBotanStruct ci $ \ pci -> do+setCipherKey ci key =+    withCipher ci $ \ pci -> do         withPrimVectorUnsafe key $ \ pkey key_off key_len -> do             throwBotanIfMinus_ (hs_botan_cipher_set_key                 pci pkey key_off key_len)@@ -610,8 +617,8 @@ -- setAssociatedData :: HasCallStack => Cipher -> V.Bytes -> IO () {-# INLINABLE setAssociatedData #-}-setAssociatedData (Cipher ci _ _ _ _ _) ad =-    withBotanStruct ci $ \ pci -> do+setAssociatedData ci ad =+    withCipher ci $ \ pci -> do         withPrimVectorUnsafe ad $ \ pad ad_off ad_len -> do             throwBotanIfMinus_ (hs_botan_cipher_set_associated_data                 pci pad ad_off ad_len)@@ -623,8 +630,8 @@             -> V.Bytes      -- ^ nonce             -> IO () {-# INLINABLE startCipher #-}-startCipher (Cipher ci _ _ _ _ _) nonce =-    withBotanStruct ci $ \ pci -> do+startCipher ci nonce =+    withCipher ci $ \ pci -> do         withPrimVectorUnsafe nonce $ \ pnonce nonce_off nonce_len -> do             throwBotanIfMinus_ (hs_botan_cipher_start                 pci pnonce nonce_off nonce_len)@@ -638,8 +645,8 @@              -> V.Bytes              -> IO (V.Bytes, V.Bytes)   -- ^ trailing input, output {-# INLINABLE updateCipher #-}-updateCipher (Cipher ci _ _ _ _ _) input =-    withBotanStruct ci $ \ pci -> do+updateCipher ci input =+    withCipher ci $ \ pci -> do         withPrimVectorUnsafe input $ \ in_p in_off in_len -> do             (out, r) <- allocPrimVectorUnsafe in_len $ \ out_p ->                 throwBotanIfMinus (hs_botan_cipher_update pci@@ -655,7 +662,7 @@              -> V.Bytes              -> IO V.Bytes {-# INLINABLE finishCipher #-}-finishCipher (Cipher ci _ ug _ tag_len _) input =+finishCipher (Cipher ci _ ug _ tag_len _ _) input =     withBotanStruct ci $ \ pci -> do         withPrimVectorUnsafe input $ \ in_p in_off in_len -> do             let !out_len = in_len + ug + tag_len@@ -669,25 +676,44 @@  -- | Wrap a cipher into a 'BIO' node(experimental). ----- The cipher should have already started by setting key, nounce, etc.+-- The cipher should have already started by setting key, nounce, etc,+-- for example to encrypt a file in constant memory: ----- Note some cipher modes have a minimal input length requirement for last chunk(CBC_CTS, XTS, etc.),--- which may not be suitable for arbitrary bytes streams.+-- @+-- encryptFile :: CBytes -> CBytes -> IO ()+-- encryptFile origin target = do+--     let demoKey = "12345678123456781234567812345678"+--         nonce = "demo only, use random nonce"+--     cipher <- newCipher (EAX AES256) CipherEncrypt+--     setCipherKey cipher demoKey+--     startCipher cipher nonce+--     encryptor <- cipherBIO cipher --+--     withResource (initSourceFromFile origin) $ \ src ->+--         withResource (initSinkToFile target) $ \ sink ->+--             runBIO_ $ src . encryptor . sink+-- @+--+-- Note that many cipher modes have a maximum length limit on the plaintext under a security context,+-- i.e. a key nonce combination. If you want to encrypt a large message, please consider divide it into+-- smaller chunks, and re-key or change the iv. cipherBIO :: HasCallStack => Cipher -> IO (BIO V.Bytes V.Bytes) {-# INLINABLE cipherBIO #-} cipherBIO c = do     trailingRef <- newIORef V.empty     return $ \ k mbs -> case mbs of-        Just bs -> do+        Just chunk -> do             trailing <- readIORef trailingRef-            let chunk =  trailing `V.append` bs-            (rest, out) <- updateCipher c chunk-            writeIORef trailingRef rest-            unless (V.null out) (k (Just out))+            if (V.length trailing >= cipherUpdateGranularity c)+                && (V.length chunk >= cipherMinFinalSize c)+            then do+                (rest, out) <- updateCipher c trailing+                k (Just out)+                writeIORef trailingRef (rest `V.append` chunk)+            else writeIORef trailingRef (trailing `V.append` chunk)         _ -> do             trailing <- readIORef trailingRef             bs <- finishCipher c trailing             if V.null bs-            then k (Just bs) >> k EOF-            else k EOF+            then k EOF+            else k (Just bs) >> k EOF
third_party/botan/botan_all.cpp view

file too large to diff

third_party/botan/src/lib/ffi/ffi.h view
@@ -451,6 +451,11 @@ BOTAN_PUBLIC_API(2,0) int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t* tag_size);  /**+* Get the minimum input size required of the cipher.+*/+BOTAN_PUBLIC_API(2,19) int botan_cipher_get_minimum_final_size(botan_cipher_t cipher, size_t* fs);++/** * Get the default nonce length of this cipher */ BOTAN_PUBLIC_API(2,0) int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t* nl);
third_party/botan/src/lib/ffi/ffi_cipher.cpp view
@@ -224,6 +224,11 @@    return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *tl = c.tag_size(); });    } +int botan_cipher_get_minimum_final_size(botan_cipher_t cipher, size_t* fs)+   {+   return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *fs = c.minimum_final_size(); });+   }+ int botan_cipher_name(botan_cipher_t cipher, char* name, size_t* name_len)    {    return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, {