{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Crypto.ECC.Edwards25519
( Scalar
, Point
, scalarGenerate
, scalarDecodeLong
, scalarEncode
, pointDecode
, pointEncode
, pointHasPrimeOrder
, toPoint
, scalarAdd
, scalarMul
, pointNegate
, pointAdd
, pointDouble
, pointMul
, pointMulByCofactor
, pointsMulVarTime
) where
import Data.Word
import Foreign.C.Types
import Foreign.Ptr
import Crypto.Error
import Crypto.Internal.ByteArray (Bytes, ScrubbedBytes, withByteArray)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Internal.Compat
import Crypto.Internal.Imports
import Crypto.Random
scalarArraySize :: Int
scalarArraySize :: Int
scalarArraySize = Int
40
newtype Scalar = Scalar ScrubbedBytes
deriving (Int -> Scalar -> ShowS
[Scalar] -> ShowS
Scalar -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Scalar] -> ShowS
$cshowList :: [Scalar] -> ShowS
show :: Scalar -> String
$cshow :: Scalar -> String
showsPrec :: Int -> Scalar -> ShowS
$cshowsPrec :: Int -> Scalar -> ShowS
Show,Scalar -> ()
forall a. (a -> ()) -> NFData a
rnf :: Scalar -> ()
$crnf :: Scalar -> ()
NFData)
instance Eq Scalar where
(Scalar ScrubbedBytes
s1) == :: Scalar -> Scalar -> Bool
== (Scalar ScrubbedBytes
s2) = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
s1 forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
ps1 ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
s2 forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
ps2 ->
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Eq a => a -> a -> Bool
/= CInt
0) (Ptr Scalar -> Ptr Scalar -> IO CInt
ed25519_scalar_eq Ptr Scalar
ps1 Ptr Scalar
ps2)
{-# NOINLINE (==) #-}
pointArraySize :: Int
pointArraySize :: Int
pointArraySize = Int
160
newtype Point = Point Bytes
deriving Point -> ()
forall a. (a -> ()) -> NFData a
rnf :: Point -> ()
$crnf :: Point -> ()
NFData
instance Show Point where
showsPrec :: Int -> Point -> ShowS
showsPrec Int
d Point
p =
let bs :: Bytes
bs = forall bs. ByteArray bs => Point -> bs
pointEncode Point
p :: Bytes
in Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
> Int
10) forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
"Point "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> ShowS
shows (forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
B.convertToBase Base
B.Base16 Bytes
bs :: Bytes)
instance Eq Point where
(Point Bytes
p1) == :: Point -> Point -> Bool
== (Point Bytes
p2) = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
p1 forall a b. (a -> b) -> a -> b
$ \Ptr Point
pp1 ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
p2 forall a b. (a -> b) -> a -> b
$ \Ptr Point
pp2 ->
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Eq a => a -> a -> Bool
/= CInt
0) (Ptr Point -> Ptr Point -> IO CInt
ed25519_point_eq Ptr Point
pp1 Ptr Point
pp2)
{-# NOINLINE (==) #-}
scalarGenerate :: MonadRandom randomly => randomly Scalar
scalarGenerate :: forall (randomly :: * -> *).
MonadRandom randomly =>
randomly Scalar
scalarGenerate = forall a. CryptoFailable a -> a
throwCryptoError forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall bs. ByteArrayAccess bs => bs -> CryptoFailable Scalar
scalarDecodeLong forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (randomly :: * -> *).
MonadRandom randomly =>
randomly ScrubbedBytes
generate
where
generate :: MonadRandom randomly => randomly ScrubbedBytes
generate :: forall (randomly :: * -> *).
MonadRandom randomly =>
randomly ScrubbedBytes
generate = forall (m :: * -> *) byteArray.
(MonadRandom m, ByteArray byteArray) =>
Int -> m byteArray
getRandomBytes Int
64
scalarEncode :: B.ByteArray bs => Scalar -> bs
scalarEncode :: forall bs. ByteArray bs => Scalar -> bs
scalarEncode (Scalar ScrubbedBytes
s) =
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
32 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
s forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
ps -> Ptr Word8 -> Ptr Scalar -> IO ()
ed25519_scalar_encode Ptr Word8
out Ptr Scalar
ps
scalarDecodeLong :: B.ByteArrayAccess bs => bs -> CryptoFailable Scalar
scalarDecodeLong :: forall bs. ByteArrayAccess bs => bs -> CryptoFailable Scalar
scalarDecodeLong bs
bs
| forall ba. ByteArrayAccess ba => ba -> Int
B.length bs
bs forall a. Ord a => a -> a -> Bool
> Int
64 = forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_EcScalarOutOfBounds
| Bool
otherwise = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs
bs Ptr Word8 -> IO (CryptoFailable Scalar)
initialize
where
len :: CSize
len = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall ba. ByteArrayAccess ba => ba -> Int
B.length bs
bs
initialize :: Ptr Word8 -> IO (CryptoFailable Scalar)
initialize Ptr Word8
inp = do
ScrubbedBytes
s <- forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
B.alloc Int
scalarArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
ps ->
Ptr Scalar -> Ptr Word8 -> CSize -> IO ()
ed25519_scalar_decode_long Ptr Scalar
ps Ptr Word8
inp CSize
len
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> CryptoFailable a
CryptoPassed (ScrubbedBytes -> Scalar
Scalar ScrubbedBytes
s)
{-# NOINLINE scalarDecodeLong #-}
scalarAdd :: Scalar -> Scalar -> Scalar
scalarAdd :: Scalar -> Scalar -> Scalar
scalarAdd (Scalar ScrubbedBytes
a) (Scalar ScrubbedBytes
b) =
ScrubbedBytes -> Scalar
Scalar forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
scalarArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
a forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
pa ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
b forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
pb ->
Ptr Scalar -> Ptr Scalar -> Ptr Scalar -> IO ()
ed25519_scalar_add Ptr Scalar
out Ptr Scalar
pa Ptr Scalar
pb
scalarMul :: Scalar -> Scalar -> Scalar
scalarMul :: Scalar -> Scalar -> Scalar
scalarMul (Scalar ScrubbedBytes
a) (Scalar ScrubbedBytes
b) =
ScrubbedBytes -> Scalar
Scalar forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
scalarArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
a forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
pa ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
b forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
pb ->
Ptr Scalar -> Ptr Scalar -> Ptr Scalar -> IO ()
ed25519_scalar_mul Ptr Scalar
out Ptr Scalar
pa Ptr Scalar
pb
toPoint :: Scalar -> Point
toPoint :: Scalar -> Point
toPoint (Scalar ScrubbedBytes
scalar) =
Bytes -> Point
Point forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
pointArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Point
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
scalar forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
pscalar ->
Ptr Point -> Ptr Scalar -> IO ()
ed25519_point_base_scalarmul Ptr Point
out Ptr Scalar
pscalar
pointEncode :: B.ByteArray bs => Point -> bs
pointEncode :: forall bs. ByteArray bs => Point -> bs
pointEncode (Point Bytes
p) =
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
32 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
p forall a b. (a -> b) -> a -> b
$ \Ptr Point
pp ->
Ptr Word8 -> Ptr Point -> IO ()
ed25519_point_encode Ptr Word8
out Ptr Point
pp
pointDecode :: B.ByteArrayAccess bs => bs -> CryptoFailable Point
pointDecode :: forall bs. ByteArrayAccess bs => bs -> CryptoFailable Point
pointDecode bs
bs
| forall ba. ByteArrayAccess ba => ba -> Int
B.length bs
bs forall a. Eq a => a -> a -> Bool
== Int
32 = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs
bs Ptr Word8 -> IO (CryptoFailable Point)
initialize
| Bool
otherwise = forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_PointSizeInvalid
where
initialize :: Ptr Word8 -> IO (CryptoFailable Point)
initialize Ptr Word8
inp = do
(CInt
res, Bytes
p) <- forall ba p a. ByteArray ba => Int -> (Ptr p -> IO a) -> IO (a, ba)
B.allocRet Int
pointArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Point
pp ->
Ptr Point -> Ptr Word8 -> IO CInt
ed25519_point_decode_vartime Ptr Point
pp Ptr Word8
inp
if CInt
res forall a. Eq a => a -> a -> Bool
== CInt
0 then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_PointCoordinatesInvalid
else forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> CryptoFailable a
CryptoPassed (Bytes -> Point
Point Bytes
p)
{-# NOINLINE pointDecode #-}
pointHasPrimeOrder :: Point -> Bool
pointHasPrimeOrder :: Point -> Bool
pointHasPrimeOrder (Point Bytes
p) = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
p forall a b. (a -> b) -> a -> b
$ \Ptr Point
pp ->
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Eq a => a -> a -> Bool
/= CInt
0) (Ptr Point -> IO CInt
ed25519_point_has_prime_order Ptr Point
pp)
{-# NOINLINE pointHasPrimeOrder #-}
pointNegate :: Point -> Point
pointNegate :: Point -> Point
pointNegate (Point Bytes
a) =
Bytes -> Point
Point forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
pointArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Point
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
a forall a b. (a -> b) -> a -> b
$ \Ptr Point
pa ->
Ptr Point -> Ptr Point -> IO ()
ed25519_point_negate Ptr Point
out Ptr Point
pa
pointAdd :: Point -> Point -> Point
pointAdd :: Point -> Point -> Point
pointAdd (Point Bytes
a) (Point Bytes
b) =
Bytes -> Point
Point forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
pointArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Point
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
a forall a b. (a -> b) -> a -> b
$ \Ptr Point
pa ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
b forall a b. (a -> b) -> a -> b
$ \Ptr Point
pb ->
Ptr Point -> Ptr Point -> Ptr Point -> IO ()
ed25519_point_add Ptr Point
out Ptr Point
pa Ptr Point
pb
pointDouble :: Point -> Point
pointDouble :: Point -> Point
pointDouble (Point Bytes
a) =
Bytes -> Point
Point forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
pointArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Point
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
a forall a b. (a -> b) -> a -> b
$ \Ptr Point
pa ->
Ptr Point -> Ptr Point -> IO ()
ed25519_point_double Ptr Point
out Ptr Point
pa
pointMulByCofactor :: Point -> Point
pointMulByCofactor :: Point -> Point
pointMulByCofactor (Point Bytes
a) =
Bytes -> Point
Point forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
pointArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Point
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
a forall a b. (a -> b) -> a -> b
$ \Ptr Point
pa ->
Ptr Point -> Ptr Point -> IO ()
ed25519_point_mul_by_cofactor Ptr Point
out Ptr Point
pa
pointMul :: Scalar -> Point -> Point
pointMul :: Scalar -> Point -> Point
pointMul (Scalar ScrubbedBytes
scalar) (Point Bytes
base) =
Bytes -> Point
Point forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
pointArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Point
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
scalar forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
pscalar ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
base forall a b. (a -> b) -> a -> b
$ \Ptr Point
pbase ->
Ptr Point -> Ptr Point -> Ptr Scalar -> IO ()
ed25519_point_scalarmul Ptr Point
out Ptr Point
pbase Ptr Scalar
pscalar
pointsMulVarTime :: Scalar -> Scalar -> Point -> Point
pointsMulVarTime :: Scalar -> Scalar -> Point -> Point
pointsMulVarTime (Scalar ScrubbedBytes
s1) (Scalar ScrubbedBytes
s2) (Point Bytes
p) =
Bytes -> Point
Point forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
pointArraySize forall a b. (a -> b) -> a -> b
$ \Ptr Point
out ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
s1 forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
ps1 ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
s2 forall a b. (a -> b) -> a -> b
$ \Ptr Scalar
ps2 ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Bytes
p forall a b. (a -> b) -> a -> b
$ \Ptr Point
pp ->
Ptr Point -> Ptr Scalar -> Ptr Point -> Ptr Scalar -> IO ()
ed25519_base_double_scalarmul_vartime Ptr Point
out Ptr Scalar
ps1 Ptr Point
pp Ptr Scalar
ps2
foreign import ccall unsafe "crypton_ed25519_scalar_eq"
ed25519_scalar_eq :: Ptr Scalar
-> Ptr Scalar
-> IO CInt
foreign import ccall unsafe "crypton_ed25519_scalar_encode"
ed25519_scalar_encode :: Ptr Word8
-> Ptr Scalar
-> IO ()
foreign import ccall unsafe "crypton_ed25519_scalar_decode_long"
ed25519_scalar_decode_long :: Ptr Scalar
-> Ptr Word8
-> CSize
-> IO ()
foreign import ccall unsafe "crypton_ed25519_scalar_add"
ed25519_scalar_add :: Ptr Scalar
-> Ptr Scalar
-> Ptr Scalar
-> IO ()
foreign import ccall unsafe "crypton_ed25519_scalar_mul"
ed25519_scalar_mul :: Ptr Scalar
-> Ptr Scalar
-> Ptr Scalar
-> IO ()
foreign import ccall unsafe "crypton_ed25519_point_encode"
ed25519_point_encode :: Ptr Word8
-> Ptr Point
-> IO ()
foreign import ccall unsafe "crypton_ed25519_point_decode_vartime"
ed25519_point_decode_vartime :: Ptr Point
-> Ptr Word8
-> IO CInt
foreign import ccall unsafe "crypton_ed25519_point_eq"
ed25519_point_eq :: Ptr Point
-> Ptr Point
-> IO CInt
foreign import ccall "crypton_ed25519_point_has_prime_order"
ed25519_point_has_prime_order :: Ptr Point
-> IO CInt
foreign import ccall unsafe "crypton_ed25519_point_negate"
ed25519_point_negate :: Ptr Point
-> Ptr Point
-> IO ()
foreign import ccall unsafe "crypton_ed25519_point_add"
ed25519_point_add :: Ptr Point
-> Ptr Point
-> Ptr Point
-> IO ()
foreign import ccall unsafe "crypton_ed25519_point_double"
ed25519_point_double :: Ptr Point
-> Ptr Point
-> IO ()
foreign import ccall unsafe "crypton_ed25519_point_mul_by_cofactor"
ed25519_point_mul_by_cofactor :: Ptr Point
-> Ptr Point
-> IO ()
foreign import ccall "crypton_ed25519_point_base_scalarmul"
ed25519_point_base_scalarmul :: Ptr Point
-> Ptr Scalar
-> IO ()
foreign import ccall "crypton_ed25519_point_scalarmul"
ed25519_point_scalarmul :: Ptr Point
-> Ptr Point
-> Ptr Scalar
-> IO ()
foreign import ccall "crypton_ed25519_base_double_scalarmul_vartime"
ed25519_base_double_scalarmul_vartime :: Ptr Point
-> Ptr Scalar
-> Ptr Point
-> Ptr Scalar
-> IO ()