chacha

The ChaCha20 stream cipher (docs.ppad.tech/chacha).
git clone git://git.ppad.tech/chacha.git
Log | Files | Refs | README | LICENSE

Arm.hs (2662B)


      1 {-# OPTIONS_HADDOCK hide #-}
      2 {-# LANGUAGE BangPatterns #-}
      3 
      4 -- |
      5 -- Module: Crypto.Cipher.ChaCha20.Arm
      6 -- Copyright: (c) 2025 Jared Tobin
      7 -- License: MIT
      8 -- Maintainer: Jared Tobin <jared@ppad.tech>
      9 --
     10 -- ARM NEON support for the ChaCha20 stream cipher.
     11 
     12 module Crypto.Cipher.ChaCha20.Arm (
     13     chacha20_arm_available
     14   , block
     15   , cipher
     16   ) where
     17 
     18 import qualified Data.ByteString as BS
     19 import qualified Data.ByteString.Internal as BI
     20 import Data.Word (Word8, Word32)
     21 import Foreign.C.Types (CInt(..), CSize(..))
     22 import Foreign.ForeignPtr (withForeignPtr)
     23 import Foreign.Ptr (Ptr, plusPtr)
     24 import System.IO.Unsafe (unsafeDupablePerformIO)
     25 
     26 -- ffi ------------------------------------------------------------------------
     27 
     28 foreign import ccall unsafe "chacha20_block_arm"
     29   c_chacha20_block
     30     :: Ptr Word8 -> Word32 -> Ptr Word8 -> Ptr Word8 -> IO ()
     31 
     32 foreign import ccall unsafe "chacha20_cipher_arm"
     33   c_chacha20_cipher
     34     :: Ptr Word8 -> Word32 -> Ptr Word8
     35     -> Ptr Word8 -> Ptr Word8 -> CSize -> IO ()
     36 
     37 foreign import ccall unsafe "chacha20_arm_available"
     38   c_chacha20_arm_available :: IO CInt
     39 
     40 -- utilities ------------------------------------------------------------------
     41 
     42 fi :: (Integral a, Num b) => a -> b
     43 fi = fromIntegral
     44 {-# INLINE fi #-}
     45 
     46 -- api ------------------------------------------------------------------------
     47 
     48 -- | Are ARM NEON extensions available?
     49 chacha20_arm_available :: Bool
     50 chacha20_arm_available =
     51   unsafeDupablePerformIO c_chacha20_arm_available /= 0
     52 {-# NOINLINE chacha20_arm_available #-}
     53 
     54 -- | One 64-byte ChaCha20 keystream block for the given (already-
     55 --   validated) key, counter, and nonce.
     56 block :: BS.ByteString -> Word32 -> BS.ByteString -> BS.ByteString
     57 block (BI.PS kfp koff _) counter (BI.PS nfp noff _) =
     58   BI.unsafeCreate 64 $ \dst ->
     59     withForeignPtr kfp $ \kp0 ->
     60     withForeignPtr nfp $ \np0 ->
     61       c_chacha20_block (kp0 `plusPtr` koff)
     62                        counter
     63                        (np0 `plusPtr` noff)
     64                        dst
     65 
     66 -- | XOR the plaintext with the ChaCha20 keystream derived from the
     67 --   given (already-validated) key, counter, and nonce.
     68 cipher
     69   :: BS.ByteString -> Word32 -> BS.ByteString -> BS.ByteString
     70   -> BS.ByteString
     71 cipher (BI.PS kfp koff _) counter (BI.PS nfp noff _)
     72        (BI.PS pfp poff plen) =
     73   BI.unsafeCreate plen $ \dst ->
     74     withForeignPtr kfp $ \kp0 ->
     75     withForeignPtr nfp $ \np0 ->
     76     withForeignPtr pfp $ \pp0 ->
     77       c_chacha20_cipher (kp0 `plusPtr` koff)
     78                         counter
     79                         (np0 `plusPtr` noff)
     80                         (pp0 `plusPtr` poff)
     81                         dst
     82                         (fi plen)