{-# LANGUAGE Safe #-}
module Crypto.NewHope.Reduce (montgomeryReduce) where
import Data.Bits
import Data.ByteString.Builder (toLazyByteString, word32BE)
import Data.ByteString.Lazy (unpack)
import Data.Word
import qualified Crypto.NewHope.Internals as Internals (q)
qinv :: Word32
qinv = 12287
rlog :: Int
rlog = 18
low16 :: Word32 -> Word16
low16 n = shiftL hb 8 + lb where
bytes = drop 2 $ unpack $ toLazyByteString $ word32BE n
hb = fromIntegral (bytes !! 0)
lb = fromIntegral (bytes !! 1)
montgomeryReduce :: Word32 -> Word16
montgomeryReduce a = low16 result
where
u = a * qinv
u' = u .&. (shiftL 1 rlog - 1 )
u'' = u' * fromIntegral Internals.q
a' = a + u''
result = shiftR a' rlog