Files
simple_crypto/test-generator/ED25519.hs
Adam Wick d459850c54 This is a very naive Rust tanslation of the basic math behind the ed25519 crypto scheme.
In general, it's a straight translation of the Google code, which in
turn is "mostly taken from the ref10 version of Ed25519 in SUPERCOP
10241124.", except that it's been hand translated to rust with some
test case generators. Future versions should clean this up to be more
normally rust-y.
2019-05-14 21:54:59 -07:00

701 lines
25 KiB
Haskell

{-# LANGUAGE PackageImports #-}
module ED25519(ed25519Tasks)
where
import Control.Monad(unless)
import "crypto-api" Crypto.Random(SystemRandom)
import "cryptonite" Crypto.Random(getRandomBytes,withDRG)
import Data.ByteString(ByteString,pack,useAsCString)
import qualified Data.ByteString as BS
import Data.Int(Int32)
import qualified Data.Map.Strict as Map
import Data.Word(Word8,Word32,Word64)
import ED25519.PrecompPoints
import Foreign.C.Types(CChar)
import Foreign.Marshal.Alloc(alloca)
import Foreign.Marshal.Array(allocaArray,peekArray,pokeArray)
import Foreign.Ptr(Ptr,castPtr)
import Foreign.Storable(Storable(..))
import Math(showX,showBin)
import Task(Task(..))
cTEST_COUNT :: Int
cTEST_COUNT = 1000
ed25519Tasks :: [Task]
ed25519Tasks = [ loadTests, byteTests, addsubTests, mulTests,
squaringTests, inversionTests, negateTests,
cmovTests, isTests, square2Tests,
pow22523Tests, fbvTests, conversionTests,
ptDoubleTests, maddsubTests, ptAddSubTests,
scalarMultBaseTests, slideTests, scalarMultTests,
reduceTests, muladdTests, pubPrivTests ]
loadTests :: Task
loadTests = Task {
taskName = "ed25519 byte loading",
taskFile = "../testdata/ed25519/load.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
do let (bytes, drg1) = withDRG drg0 (getRandomBytes 4)
res3 <- useAsCString bytes (\ptr -> load_3 ptr)
res4 <- useAsCString bytes (\ptr -> load_4 ptr)
let res = Map.fromList [("x", showBin bytes), ("a", showX res3), ("b", showX res4)]
return (res, fromIntegral res4, (memory0, drg1))
byteTests :: Task
byteTests = Task {
taskName = "ed25519 byte / element conversion",
taskFile = "../testdata/ed25519/bytes.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPackedBytes drg0 $ \ ptra drg1 ->
alloca $ \ ptrc ->
allocaArray 32 $ \ rptr ->
do clearSpace ptrc
pokeArray (rptr :: Ptr Word8) (replicate 32 0)
fe_frombytes ptrc ptra
b <- convertFE ptrc
fe_tobytes (castPtr rptr) ptrc
start <- peek ptra
end <- peek (castPtr rptr)
unless (start == end) $
fail "field element tobytes/frombytes doesn't round trip"
bytes' <- pack `fmap` peekArray 32 (castPtr ptra :: Ptr Word8)
let res = Map.fromList [("a", showBin bytes'),
("b", showBin b)]
return (res, toNumber b, (memory0, drg1))
addsubTests :: Task
addsubTests = Task {
taskName = "ed25519 addition/subtraction tests",
taskFile = "../testdata/ed25519/addsub.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ ptrel1 drg1 ->
randomElement drg1 $ \ ptrel2 drg2 ->
alloca $ \ ptrc ->
alloca $ \ ptrd ->
do fe_add ptrc ptrel1 ptrel2
fe_sub ptrd ptrel1 ptrel2
[a, b, c, d] <- mapM convertFE [ptrel1, ptrel2, ptrc, ptrd]
let res = Map.fromList [("a", showBin a),
("b", showBin b),
("c", showBin c),
("d", showBin d)]
return (res, toNumber c, (memory0, drg2))
mulTests :: Task
mulTests = Task {
taskName = "ed25519 multiplication tests",
taskFile = "../testdata/ed25519/mul.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ ptrel1 drg1 ->
randomElement drg1 $ \ ptrel2 drg2 ->
alloca $ \ ptrc ->
do fe_mul ptrc ptrel1 ptrel2
[a, b, c] <- mapM convertFE [ptrel1, ptrel2, ptrc]
let res = Map.fromList [("a", showBin a),
("b", showBin b),
("c", showBin c)]
return (res, toNumber c, (memory0, drg2))
squaringTests :: Task
squaringTests = Task {
taskName = "ed25519 squaring tests",
taskFile = "../testdata/ed25519/square.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ ptrel drg1 ->
alloca $ \ ptrc ->
do fe_square ptrc ptrel
[a, c] <- mapM convertFE [ptrel, ptrc]
let res = Map.fromList [("a", showBin a),
("c", showBin c)]
return (res, toNumber c, (memory0, drg1))
inversionTests :: Task
inversionTests = Task {
taskName = "ed25519 inversion tests",
taskFile = "../testdata/ed25519/invert.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ ptrel drg1 ->
alloca $ \ ptrc ->
do fe_invert ptrc ptrel
a <- convertFE ptrel
c <- convertFE ptrc
let res = Map.fromList [("a", showBin a),
("c", showBin c)]
return (res, toNumber a, (memory0, drg1))
negateTests :: Task
negateTests = Task {
taskName = "ed25519 negation tests",
taskFile = "../testdata/ed25519/negate.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ ptrel drg1 ->
alloca $ \ ptrc ->
do fe_negate ptrc ptrel
a <- convertFE ptrel
c <- convertFE ptrc
let res = Map.fromList [("a", showBin a),
("c", showBin c)]
return (res, toNumber a, (memory0, drg1))
cmovTests :: Task
cmovTests = Task {
taskName = "ed25519 conditional mov tests",
taskFile = "../testdata/ed25519/cmov.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ aelptr drg1 ->
do let (bbytes, drg2) = withDRG drg1 (getRandomBytes 1)
b = even (BS.head bbytes)
bvalLib = if b then 0 else 1
bvalOut = if b then 0 else 0xFFFFFF :: Word32
alloca $ \ celptr ->
do clearSpace celptr
fe_cmov celptr aelptr bvalLib
a <- convertFE aelptr
c <- convertFE celptr
let res = Map.fromList [("a", showBin a),
("b", showX bvalOut),
("c", showBin c)]
return (res, toNumber a, (memory0, drg2))
isTests :: Task
isTests = Task {
taskName = "ed25519 predicate tests",
taskFile = "../testdata/ed25519/istests.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ aptr drg1 ->
do a <- convertFE aptr
z <- fe_isnonzero aptr
n <- fe_isnegative aptr
let res = Map.fromList [("a", showBin a),
("z", showX (if z == 0 then 0 :: Word32 else 0xFFFFFF)),
("n", showX (if n == 0 then 0 :: Word32 else 0xFFFFFF))]
return (res, toNumber a, (memory0, drg1))
square2Tests :: Task
square2Tests = Task {
taskName = "ed25519 square2 tests",
taskFile = "../testdata/ed25519/square2.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ aptr drg1 ->
alloca $ \ cptr ->
do clearSpace cptr
fe_square2 cptr aptr
a <- convertFE aptr
c <- convertFE cptr
let res = Map.fromList [("a", showBin a), ("c", showBin c)]
return (res, toNumber a, (memory0, drg1))
pow22523Tests :: Task
pow22523Tests = Task {
taskName = "ed25519 pow22523 tests",
taskFile = "../testdata/ed25519/pow22523.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomElement drg0 $ \ aptr drg1 ->
alloca $ \ cptr ->
do clearSpace cptr
fe_pow22523 cptr aptr
a <- convertFE aptr
c <- convertFE cptr
let res = Map.fromList [("a", showBin a), ("c", showBin c)]
return (res, toNumber a, (memory0, drg1))
fbvTests :: Task
fbvTests = Task {
taskName = "ed25519 from bytes (vartime) tests",
taskFile = "../testdata/ed25519/fbv.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
do let (abytes, drg1) = withDRG drg0 (getRandomBytes 32)
useAsCString abytes $ \ aptr ->
do let aptr' = castPtr aptr :: Ptr PackedBytes
curve25519_scalar_mask aptr'
alloca $ \ dest ->
do clearSpace dest
point_frombytes dest aptr'
a <- pack `fmap` peekArray 32 (castPtr aptr)
c <- pack `fmap` peekArray (4 * 10 * 4) (castPtr dest)
let res = Map.fromList [("a", showBin a), ("c", showBin c)]
return (res, toNumber abytes, (memory0, drg1))
conversionTests :: Task
conversionTests = Task {
taskName = "ed25519 point form conversion tests",
taskFile = "../testdata/ed25519/conversion.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPoint3 drg0 $ \ ptr3 drg' ->
alloca $ \ ptrCached ->
alloca $ \ ptr2 ->
alloca $ \ ptrP1P1 ->
alloca $ \ ptr2' ->
alloca $ \ ptr3' ->
do clearSpace ptrCached
clearSpace ptr2
clearSpace ptrP1P1
clearSpace ptr2'
clearSpace ptr3'
p3_to_cached ptrCached ptr3
ge_p3_to_p2 ptr2 ptr3
ge_p3_dbl ptrP1P1 ptr3
p1p1_to_p2 ptr2' ptrP1P1
p1p1_to_p3 ptr3' ptrP1P1
a <- convertPoint ptr3
c <- convertPoint ptrCached
t <- convertPoint ptr2
o <- convertPoint ptrP1P1
d <- convertPoint ptr2'
b <- convertPoint ptr3'
let res = Map.fromList [("a", showBin a), ("c", showBin c),
("t", showBin t), ("o", showBin o),
("d", showBin d), ("b", showBin b)]
return (res, toNumber a, (memory0, drg'))
ptDoubleTests :: Task
ptDoubleTests = Task {
taskName = "ed25519 point doubling tests",
taskFile = "../testdata/ed25519/pt_double.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPoint3 drg0 $ \ ptra drg1 ->
randomPoint2 drg1 $ \ ptrc drg2 ->
alloca $ \ ptrb ->
alloca $ \ ptrd ->
do clearSpace ptrb
clearSpace ptrd
ge_p3_dbl ptrb ptra
ge_p2_dbl ptrd ptrc
a <- convertPoint ptra
b <- convertPoint ptrb
c <- convertPoint ptrc
d <- convertPoint ptrd
let res = Map.fromList [("a", showBin a), ("b", showBin b),
("c", showBin c), ("d", showBin d)]
return (res, toNumber a, (memory0, drg2))
maddsubTests :: Task
maddsubTests = Task {
taskName = "ed25519 point madd/msub tests",
taskFile = "../testdata/ed25519/maddsub.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPoint3 drg0 $ \ ptra drg1 ->
randomPointPrecomp drg1 $ \ ptrc drg2 ->
alloca $ \ ptrb ->
alloca $ \ ptrd ->
do clearSpace ptrb
clearSpace ptrd
ge_madd ptrb ptra ptrc
ge_msub ptrd ptra ptrc
a <- convertPoint ptra
b <- convertPoint ptrb
c <- convertPoint ptrc
d <- convertPoint ptrd
let res = Map.fromList [("a", showBin a), ("b", showBin b),
("c", showBin c), ("d", showBin d)]
return (res, toNumber a, (memory0, drg2))
ptAddSubTests :: Task
ptAddSubTests = Task {
taskName = "ed25519 point add/sub tests",
taskFile = "../testdata/ed25519/ptaddsub.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPoint3 drg0 $ \ ptra drg1 ->
randomPointCached drg1 $ \ ptrc drg2 ->
alloca $ \ ptrb ->
alloca $ \ ptrd ->
do clearSpace ptrb
clearSpace ptrd
ge_add ptrb ptra ptrc
ge_sub ptrd ptra ptrc
a <- convertPoint ptra
b <- convertPoint ptrb
c <- convertPoint ptrc
d <- convertPoint ptrd
let res = Map.fromList [("a", showBin a), ("b", showBin b),
("c", showBin c), ("d", showBin d)]
return (res, toNumber a, (memory0, drg2))
scalarMultBaseTests :: Task
scalarMultBaseTests = Task {
taskName = "ed25519 point add/sub tests",
taskFile = "../testdata/ed25519/scalar_mult.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPackedBytes drg0 $ \ ptra drg1 ->
alloca $ \ ptrb ->
do clearSpace ptrb
x25519_ge_scalarmult_base ptrb ptra
PB abytes <- peek ptra
let a = pack abytes
b <- convertPoint ptrb
let res = Map.fromList [("a", showBin a), ("b", showBin b)]
return (res, toNumber a, (memory0, drg1))
slideTests :: Task
slideTests = Task {
taskName = "ed25519 slide helper function tests",
taskFile = "../testdata/ed25519/slide.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPackedBytes drg0 $ \ ptra drg1 ->
allocaArray 256 $ \ ptrb ->
do pokeArray ptrb (replicate 256 0)
slide ptrb ptra
a <- pack `fmap` peekArray 32 (castPtr ptra)
b <- pack `fmap` peekArray 356 ptrb
let res = Map.fromList [("a", showBin a), ("b", showBin b)]
return (res, toNumber a, (memory0, drg1))
scalarMultTests :: Task
scalarMultTests = Task {
taskName = "ed25519 point general scalar multiplication tests",
taskFile = "../testdata/ed25519/scalar_mult_gen.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPackedBytes drg0 $ \ ptra drg1 ->
randomPoint3 drg1 $ \ ptrb drg2 ->
randomPackedBytes drg2 $ \ ptrc drg3 ->
alloca $ \ ptrd ->
do clearSpace ptrd
ge_double_scalarmult_vartime ptrd ptra ptrb ptrc
PB abytes <- peek ptra
let a = pack abytes
b <- convertPoint ptrb
PB cbytes <- peek ptrc
let c = pack cbytes
d <- convertPoint ptrd
let res = Map.fromList [("a", showBin a), ("b", showBin b),
("c", showBin c), ("d", showBin d)]
return (res, toNumber a, (memory0, drg3))
reduceTests :: Task
reduceTests = Task {
taskName = "ed25519 reduce tests",
taskFile = "../testdata/ed25519/reduce.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
do let (a, drg1) = withDRG drg0 (getRandomBytes 64)
allocaArray 64 $ \ target ->
do pokeArray target (BS.unpack a)
sc_reduce target
b <- pack `fmap` peekArray 32 target
let res = Map.fromList [("a", showBin a), ("b", showBin b)]
return (res, toNumber a, (memory0, drg1))
muladdTests :: Task
muladdTests = Task {
taskName = "ed25519 multiplication+addition tests",
taskFile = "../testdata/ed25519/muladd.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPackedBytes drg0 $ \ ptra drg1 ->
randomPackedBytes drg1 $ \ ptrb drg2 ->
randomPackedBytes drg2 $ \ ptrc drg3 ->
alloca $ \ ptrd ->
do clearSpace ptrd
sc_muladd ptrd ptra ptrb ptrc
a <- repackBytes ptra
b <- repackBytes ptrb
c <- repackBytes ptrc
d <- repackBytes ptrd
let res = Map.fromList [("a", showBin a), ("b", showBin b),
("c", showBin c), ("d", showBin d)]
return (res, toNumber a, (memory0, drg3))
pubPrivTests :: Task
pubPrivTests = Task {
taskName = "ed25519 private -> public conversion tests",
taskFile = "../testdata/ed25519/pubfrompriv.test",
taskTest = go,
taskCount = cTEST_COUNT
}
where
go (memory0, drg0) =
randomPackedBytes drg0 $ \ ptra drg1 ->
alloca $ \ ptrb ->
do clearSpace ptrb
public_from_private ptrb ptra
a <- repackBytes ptra
b <- repackBytes ptrb
let res = Map.fromList [("a", showBin a), ("b", showBin b)]
return (res, toNumber a, (memory0, drg1))
data PackedBytes = PB [Word8]
deriving (Eq)
instance Storable PackedBytes where
sizeOf _ = 32
alignment _ = 8
peek p = PB `fmap` peekArray 32 (castPtr p)
poke p (PB v) = pokeArray (castPtr p) v
randomPackedBytes :: SystemRandom -> (Ptr PackedBytes -> SystemRandom -> IO a) -> IO a
randomPackedBytes drg action =
do let (bytes, drg') = withDRG drg (getRandomBytes 32)
useAsCString bytes $ \ ptr ->
do let ptr' = castPtr ptr :: Ptr PackedBytes
curve25519_scalar_mask ptr'
action ptr' drg'
repackBytes :: Ptr PackedBytes -> IO ByteString
repackBytes ptr =
do PB xs <- peek ptr
return (pack xs)
data Element = FE [Int32]
instance Storable Element where
sizeOf _ = 10 * sizeOf (undefined :: Int32)
alignment _ = 8
peek p = FE `fmap` peekArray 10 (castPtr p)
poke p (FE v) = pokeArray (castPtr p) v
randomElement :: SystemRandom -> (Ptr Element -> SystemRandom -> IO a) -> IO a
randomElement drg action =
randomPackedBytes drg $ \ ptrpb drg' -> alloca $ \ ptrel ->
do clearSpace ptrel
fe_frombytes ptrel ptrpb
action ptrel drg'
data Point3 = P3 [Element]
instance Storable Point3 where
sizeOf _ = 4 * sizeOf (undefined :: Element)
alignment _ = 8
peek p = P3 `fmap` peekArray 4 (castPtr p)
poke p (P3 v) = pokeArray (castPtr p) v
randomPoint3 :: SystemRandom -> (Ptr Point3 -> SystemRandom -> IO a) -> IO a
randomPoint3 drg action =
randomPackedBytes drg $ \ aptr drg' ->
allocaArray (4 * 10) $ \ dest ->
do clearSpace dest
point_frombytes dest aptr
action (castPtr dest) drg'
data PointCached = PC [Element]
instance Storable PointCached where
sizeOf _ = 4 * sizeOf (undefined :: Element)
alignment _ = 8
peek p = PC `fmap` peekArray 4 (castPtr p)
poke p (PC v) = pokeArray (castPtr p) v
randomPointCached :: SystemRandom -> (Ptr PointCached -> SystemRandom -> IO a) -> IO a
randomPointCached drg action =
randomPoint3 drg $ \ ptr drg' ->
allocaArray (4 * 10) $ \ dest ->
do pokeArray (castPtr dest :: Ptr Int32) (replicate (4 * 10) 0)
p3_to_cached dest ptr
action (castPtr dest) drg'
data Point2 = P2 [Element]
instance Storable Point2 where
sizeOf _ = 3 * sizeOf (undefined :: Element)
alignment _ = 8
peek p = P2 `fmap` peekArray 3 (castPtr p)
poke p (P2 v) = pokeArray (castPtr p) v
randomPoint2 :: SystemRandom -> (Ptr Point2 -> SystemRandom -> IO a) -> IO a
randomPoint2 drg action =
randomPoint3 drg $ \ ptr3 drg' ->
allocaArray (3 * 10) $ \ dest ->
do pokeArray (castPtr dest :: Ptr Int32) (replicate (3 * 10) 0)
ge_p3_to_p2 dest ptr3
action (castPtr dest) drg'
data PointP1P1 = P1P1 [Element]
instance Storable PointP1P1 where
sizeOf _ = 4 * sizeOf (undefined :: Element)
alignment _ = 8
peek p = P1P1 `fmap` peekArray 4 (castPtr p)
poke p (P1P1 v) = pokeArray (castPtr p) v
_randomPointP1P1 :: SystemRandom -> (Ptr PointP1P1 -> SystemRandom -> IO a) -> IO a
_randomPointP1P1 drg action =
randomPoint3 drg $ \ ptr3 drg' ->
allocaArray (4 * 10) $ \ dest ->
do pokeArray (castPtr dest :: Ptr Int32) (replicate (4 * 10) 0)
ge_p3_dbl dest ptr3
action (castPtr dest) drg'
data PointPrecomp = PP [Element]
instance Storable PointPrecomp where
sizeOf _ = 4 * sizeOf (undefined :: Element)
alignment _ = 8
peek p = PP `fmap` peekArray 4 (castPtr p)
poke p (PP v) = pokeArray (castPtr p) v
randomPointPrecomp :: SystemRandom -> (Ptr PointPrecomp -> SystemRandom -> IO a) -> IO a
randomPointPrecomp drg action =
do let ([a,b,c,d], drg') = withDRG drg (BS.unpack `fmap` getRandomBytes 4)
mix = fromIntegral a + fromIntegral b + fromIntegral c + fromIntegral d
idx = mix `mod` (length precompPoints)
val = PP (map FE (precompPoints !! idx))
alloca $ \ ptr ->
do poke ptr val
action ptr drg'
clearSpace :: Storable a => Ptr a -> IO ()
clearSpace x = meh x undefined
where
meh :: Storable a => Ptr a -> a -> IO ()
meh p v = pokeArray (castPtr p) (replicate (sizeOf v) (0 :: Word8))
convertFE :: Ptr Element -> IO ByteString
convertFE feptr = pack `fmap` peekArray 40 (castPtr feptr :: Ptr Word8)
convertPoint :: Storable a => Ptr a -> IO ByteString
convertPoint x = meh x undefined
where
meh :: Storable a => Ptr a -> a -> IO ByteString
meh p v = pack `fmap` peekArray (sizeOf v) (castPtr p)
toNumber :: ByteString -> Integer
toNumber = BS.foldr (\ x a -> fromIntegral x + a) 0
foreign import ccall unsafe "load_3"
load_3 :: Ptr CChar -> IO Word64
foreign import ccall unsafe "load_4"
load_4 :: Ptr CChar -> IO Word64
foreign import ccall unsafe "GFp_curve25519_scalar_mask"
curve25519_scalar_mask :: Ptr PackedBytes -> IO ()
foreign import ccall unsafe "fe_frombytes"
fe_frombytes :: Ptr Element -> Ptr PackedBytes -> IO ()
foreign import ccall unsafe "GFp_fe_tobytes"
fe_tobytes :: Ptr PackedBytes -> Ptr Element -> IO ()
foreign import ccall unsafe "fe_add"
fe_add :: Ptr Element -> Ptr Element -> Ptr Element -> IO ()
foreign import ccall unsafe "fe_sub"
fe_sub :: Ptr Element -> Ptr Element -> Ptr Element -> IO ()
foreign import ccall unsafe "GFp_fe_mul"
fe_mul :: Ptr Element -> Ptr Element -> Ptr Element -> IO ()
foreign import ccall unsafe "fe_sq"
fe_square :: Ptr Element -> Ptr Element -> IO ()
foreign import ccall unsafe "GFp_fe_invert"
fe_invert :: Ptr Element -> Ptr Element -> IO ()
foreign import ccall unsafe "fe_neg"
fe_negate :: Ptr Element -> Ptr Element -> IO ()
foreign import ccall unsafe "fe_cmov"
fe_cmov :: Ptr Element -> Ptr Element -> Word32 -> IO ()
foreign import ccall unsafe "fe_isnonzero"
fe_isnonzero :: Ptr Element -> IO Int32
foreign import ccall unsafe "GFp_fe_isnegative"
fe_isnegative :: Ptr Element -> IO Word8
foreign import ccall unsafe "fe_sq2"
fe_square2 :: Ptr Element -> Ptr Element -> IO ()
foreign import ccall unsafe "fe_pow22523"
fe_pow22523 :: Ptr Element -> Ptr Element -> IO ()
foreign import ccall unsafe "GFp_x25519_ge_frombytes_vartime"
point_frombytes :: Ptr Point3 -> Ptr PackedBytes -> IO ()
foreign import ccall unsafe "x25519_ge_p3_to_cached"
p3_to_cached :: Ptr PointCached -> Ptr Point3 -> IO ()
foreign import ccall unsafe "x25519_ge_p1p1_to_p2"
p1p1_to_p2 :: Ptr Point2 -> Ptr PointP1P1 -> IO ()
foreign import ccall unsafe "x25519_ge_p1p1_to_p3"
p1p1_to_p3 :: Ptr Point3 -> Ptr PointP1P1 -> IO ()
foreign import ccall unsafe "ge_p2_dbl"
ge_p2_dbl :: Ptr PointP1P1 -> Ptr Point2 -> IO ()
foreign import ccall unsafe "ge_p3_dbl"
ge_p3_dbl :: Ptr PointP1P1 -> Ptr Point3 -> IO ()
foreign import ccall unsafe "ge_p3_to_p2"
ge_p3_to_p2 :: Ptr Point2 -> Ptr Point3 -> IO ()
foreign import ccall unsafe "ge_madd"
ge_madd :: Ptr PointP1P1 -> Ptr Point3 -> Ptr PointPrecomp -> IO ()
foreign import ccall unsafe "ge_msub"
ge_msub :: Ptr PointP1P1 -> Ptr Point3 -> Ptr PointPrecomp -> IO ()
foreign import ccall unsafe "x25519_ge_add"
ge_add :: Ptr PointP1P1 -> Ptr Point3 -> Ptr PointCached -> IO ()
foreign import ccall unsafe "x25519_ge_sub"
ge_sub :: Ptr PointP1P1 -> Ptr Point3 -> Ptr PointCached -> IO ()
foreign import ccall unsafe "GFp_x25519_ge_scalarmult_base"
x25519_ge_scalarmult_base :: Ptr Point3 -> Ptr PackedBytes -> IO ()
foreign import ccall unsafe "slide"
slide :: Ptr Word8 -> Ptr PackedBytes -> IO ()
foreign import ccall unsafe "GFp_ge_double_scalarmult_vartime"
ge_double_scalarmult_vartime :: Ptr Point2 -> Ptr PackedBytes -> Ptr Point3 -> Ptr PackedBytes -> IO ()
foreign import ccall unsafe "GFp_x25519_sc_reduce"
sc_reduce :: Ptr Word8 -> IO ()
foreign import ccall unsafe "GFp_x25519_sc_muladd"
sc_muladd :: Ptr PackedBytes -> Ptr PackedBytes -> Ptr PackedBytes -> Ptr PackedBytes -> IO ()
foreign import ccall unsafe "GFp_x25519_public_from_private"
public_from_private :: Ptr PackedBytes -> Ptr PackedBytes -> IO ()