ppad-poly1305 0.4.4 → 0.4.5
raw patch · 4 files changed
+47/−3 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG +5/−0
- lib/Crypto/MAC/Poly1305.hs +6/−2
- lib/Data/Barrier.hs +33/−0
- ppad-poly1305.cabal +3/−1
CHANGELOG view
@@ -1,5 +1,10 @@ # Changelog +- 0.4.5 (2026-07-17)+ * Adds an optimization-opaque barrier to MAC equality comparison+ to prevent LLVM from introducing variable-time instructions when+ compiling with the LLVM backend.+ - 0.4.4 (2026-07-06) * Reverts the unrolled MAC comparison introduced in 0.4.3, which was found to introduce timing variation on both aarch64 and x86-64 when
lib/Crypto/MAC/Poly1305.hs view
@@ -27,6 +27,7 @@ ) where import qualified Crypto.MAC.Poly1305.Arm as Arm+import Data.Barrier (barrier) import qualified Data.Bits as B import qualified Data.ByteString as BS import qualified Data.ByteString.Internal as BI@@ -160,10 +161,13 @@ -- fused fold: OR the bytewise XORs into an accumulator -- directly, rather than via packZipWith, so no intermediate -- ByteString holding the (secret-derived) difference bytes- -- is ever materialised on the heap.+ -- is ever materialised on the heap. The accumulator is routed+ -- through 'barrier' before the zero-test so the LLVM backend+ -- cannot recover the array-equality idiom and short-circuit on+ -- the first mismatch (see "Data.Barrier"). go :: Word8 -> Int -> Bool go !acc !i- | i == la = acc == 0+ | i == la = barrier acc == 0 | otherwise = let !x = BU.unsafeIndex a i !y = BU.unsafeIndex b i
+ lib/Data/Barrier.hs view
@@ -0,0 +1,33 @@+{-# OPTIONS_HADDOCK hide #-}++-- |+-- Module: Data.Barrier+-- Copyright: (c) 2025 Jared Tobin+-- License: MIT+-- Maintainer: Jared Tobin <jared@ppad.tech>+--+-- An optimisation barrier for constant-time code.++module Data.Barrier (+ barrier+ ) where++import Data.Word (Word8)++-- | Identity on 'Word8', but opaque to the optimiser. A constant-time+-- accumulate-then-compare (e.g. an OR-fold of bytewise XORs, tested+-- against zero) routes its accumulator through this before the+-- zero-test, so the compiler cannot recognise it as an array-equality+-- test and lower it to a short-circuiting byte comparison (which would+-- leak the mismatch position).+--+-- Both properties are required and must not be \"tidied\" away:+--+-- * @NOINLINE@ -- if GHC inlines it, the LLVM backend regains the+-- accumulator's definition and short-circuits again.+-- * a /separate/ module -- a caller then compiles @barrier@ to an+-- external call it cannot see through. Inline it into the caller+-- and the barrier is gone.+barrier :: Word8 -> Word8+barrier x = x+{-# NOINLINE barrier #-}
ppad-poly1305.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: ppad-poly1305-version: 0.4.4+version: 0.4.5 synopsis: A fast Poly1305 MAC license: MIT license-file: LICENSE@@ -38,6 +38,8 @@ exposed-modules: Crypto.MAC.Poly1305 Crypto.MAC.Poly1305.Arm+ other-modules:+ Data.Barrier build-depends: base >= 4.9 && < 5 , bytestring >= 0.9 && < 0.13