-- | Elliptic Curve Arithmetic.
--
-- /WARNING:/ These functions are vulnerable to timing attacks.
{-# LANGUAGE ScopedTypeVariables #-}
module Crypto.ECC.Simple.Prim
    ( scalarGenerate
    , scalarFromInteger
    , pointAdd
    , pointNegate
    , pointDouble
    , pointBaseMul
    , pointMul
    , pointAddTwoMuls
    , pointFromIntegers
    , isPointAtInfinity
    , isPointValid
    ) where

import Data.Maybe
import Data.Proxy
import Crypto.Number.ModArithmetic
import Crypto.Number.F2m
import Crypto.Number.Generate (generateBetween)
import Crypto.ECC.Simple.Types
import Crypto.Error
import Crypto.Random

-- | Generate a valid scalar for a specific Curve
scalarGenerate :: forall randomly curve . (MonadRandom randomly, Curve curve) => randomly (Scalar curve)
scalarGenerate :: randomly (Scalar curve)
scalarGenerate =
    Integer -> Scalar curve
forall curve. Integer -> Scalar curve
Scalar (Integer -> Scalar curve)
-> randomly Integer -> randomly (Scalar curve)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Integer -> Integer -> randomly Integer
forall (m :: * -> *).
MonadRandom m =>
Integer -> Integer -> m Integer
generateBetween Integer
1 (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)
  where
    n :: Integer
n = CurveParameters curve -> Integer
forall curve. CurveParameters curve -> Integer
curveEccN (CurveParameters curve -> Integer)
-> CurveParameters curve -> Integer
forall a b. (a -> b) -> a -> b
$ Proxy curve -> CurveParameters curve
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters (Proxy curve
forall k (t :: k). Proxy t
Proxy :: Proxy curve)

scalarFromInteger :: forall curve . Curve curve => Integer -> CryptoFailable (Scalar curve)
scalarFromInteger :: Integer -> CryptoFailable (Scalar curve)
scalarFromInteger Integer
n
    | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0  Bool -> Bool -> Bool
|| Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
mx = CryptoError -> CryptoFailable (Scalar curve)
forall a. CryptoError -> CryptoFailable a
CryptoFailed (CryptoError -> CryptoFailable (Scalar curve))
-> CryptoError -> CryptoFailable (Scalar curve)
forall a b. (a -> b) -> a -> b
$ CryptoError
CryptoError_EcScalarOutOfBounds
    | Bool
otherwise         = Scalar curve -> CryptoFailable (Scalar curve)
forall a. a -> CryptoFailable a
CryptoPassed (Scalar curve -> CryptoFailable (Scalar curve))
-> Scalar curve -> CryptoFailable (Scalar curve)
forall a b. (a -> b) -> a -> b
$ Integer -> Scalar curve
forall curve. Integer -> Scalar curve
Scalar Integer
n
  where
    mx :: Integer
mx = case Proxy curve -> CurveType
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType (Proxy curve
forall k (t :: k). Proxy t
Proxy :: Proxy curve) of
            CurveBinary (CurveBinaryParam Integer
b) -> Integer
b
            CurvePrime (CurvePrimeParam Integer
p)   -> Integer
p

--TODO: Extract helper function for `fromMaybe PointO...`

-- | Elliptic Curve point negation:
-- @pointNegate p@ returns point @q@ such that @pointAdd p q == PointO@.
pointNegate :: Curve curve => Point curve -> Point curve
pointNegate :: Point curve -> Point curve
pointNegate        Point curve
PointO     = Point curve
forall curve. Point curve
PointO
pointNegate point :: Point curve
point@(Point Integer
x Integer
y) =
    case Point curve -> CurveType
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType Point curve
point of
        CurvePrime (CurvePrimeParam Integer
p) -> Integer -> Integer -> Point curve
forall curve. Integer -> Integer -> Point curve
Point Integer
x (Integer
p Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y)
        CurveBinary {} -> Integer -> Integer -> Point curve
forall curve. Integer -> Integer -> Point curve
Point Integer
x (Integer
x Integer -> Integer -> Integer
`addF2m` Integer
y)

-- | Elliptic Curve point addition.
--
-- /WARNING:/ Vulnerable to timing attacks.
pointAdd :: Curve curve => Point curve -> Point curve -> Point curve
pointAdd :: Point curve -> Point curve -> Point curve
pointAdd Point curve
PointO Point curve
PointO = Point curve
forall curve. Point curve
PointO
pointAdd Point curve
PointO Point curve
q = Point curve
q
pointAdd Point curve
p Point curve
PointO = Point curve
p
pointAdd Point curve
p Point curve
q
  | Point curve
p Point curve -> Point curve -> Bool
forall a. Eq a => a -> a -> Bool
== Point curve
q             = Point curve -> Point curve
forall curve. Curve curve => Point curve -> Point curve
pointDouble Point curve
p
  | Point curve
p Point curve -> Point curve -> Bool
forall a. Eq a => a -> a -> Bool
== Point curve -> Point curve
forall curve. Curve curve => Point curve -> Point curve
pointNegate Point curve
q = Point curve
forall curve. Point curve
PointO
pointAdd point :: Point curve
point@(Point Integer
xp Integer
yp) (Point Integer
xq Integer
yq) =
    case CurveType
ty of
        CurvePrime (CurvePrimeParam Integer
pr) -> Point curve -> Maybe (Point curve) -> Point curve
forall a. a -> Maybe a -> a
fromMaybe Point curve
forall curve. Point curve
PointO (Maybe (Point curve) -> Point curve)
-> Maybe (Point curve) -> Point curve
forall a b. (a -> b) -> a -> b
$ do
            Integer
s <- Integer -> Integer -> Integer -> Maybe Integer
divmod (Integer
yp Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
yq) (Integer
xp Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
xq) Integer
pr
            let xr :: Integer
xr = (Integer
s Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
xp Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
xq) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
pr
                yr :: Integer
yr = (Integer
s Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
xp Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
xr) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
yp) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
pr
            Point curve -> Maybe (Point curve)
forall (m :: * -> *) a. Monad m => a -> m a
return (Point curve -> Maybe (Point curve))
-> Point curve -> Maybe (Point curve)
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Point curve
forall curve. Integer -> Integer -> Point curve
Point Integer
xr Integer
yr
        CurveBinary (CurveBinaryParam Integer
fx) -> Point curve -> Maybe (Point curve) -> Point curve
forall a. a -> Maybe a -> a
fromMaybe Point curve
forall curve. Point curve
PointO (Maybe (Point curve) -> Point curve)
-> Maybe (Point curve) -> Point curve
forall a b. (a -> b) -> a -> b
$ do
            Integer
s <- Integer -> Integer -> Integer -> Maybe Integer
divF2m Integer
fx (Integer
yp Integer -> Integer -> Integer
`addF2m` Integer
yq) (Integer
xp Integer -> Integer -> Integer
`addF2m` Integer
xq)
            let xr :: Integer
xr = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
s Integer
s Integer -> Integer -> Integer
`addF2m` Integer
s Integer -> Integer -> Integer
`addF2m` Integer
xp Integer -> Integer -> Integer
`addF2m` Integer
xq Integer -> Integer -> Integer
`addF2m` Integer
a
                yr :: Integer
yr = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
s (Integer
xp Integer -> Integer -> Integer
`addF2m` Integer
xr) Integer -> Integer -> Integer
`addF2m` Integer
xr Integer -> Integer -> Integer
`addF2m` Integer
yp
            Point curve -> Maybe (Point curve)
forall (m :: * -> *) a. Monad m => a -> m a
return (Point curve -> Maybe (Point curve))
-> Point curve -> Maybe (Point curve)
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Point curve
forall curve. Integer -> Integer -> Point curve
Point Integer
xr Integer
yr
  where
    ty :: CurveType
ty = Point curve -> CurveType
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType Point curve
point
    cc :: CurveParameters curve
cc = Point curve -> CurveParameters curve
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters Point curve
point
    a :: Integer
a  = CurveParameters curve -> Integer
forall curve. CurveParameters curve -> Integer
curveEccA CurveParameters curve
cc

-- | Elliptic Curve point doubling.
--
-- /WARNING:/ Vulnerable to timing attacks.
--
-- This perform the following calculation:
-- > lambda = (3 * xp ^ 2 + a) / 2 yp
-- > xr = lambda ^ 2 - 2 xp
-- > yr = lambda (xp - xr) - yp
--
-- With binary curve:
-- > xp == 0   => P = O
-- > otherwise =>
-- >    s = xp + (yp / xp)
-- >    xr = s ^ 2 + s + a
-- >    yr = xp ^ 2 + (s+1) * xr
--
pointDouble :: Curve curve => Point curve -> Point curve
pointDouble :: Point curve -> Point curve
pointDouble Point curve
PointO = Point curve
forall curve. Point curve
PointO
pointDouble point :: Point curve
point@(Point Integer
xp Integer
yp) =
    case CurveType
ty of
        CurvePrime (CurvePrimeParam Integer
pr) -> Point curve -> Maybe (Point curve) -> Point curve
forall a. a -> Maybe a -> a
fromMaybe Point curve
forall curve. Point curve
PointO (Maybe (Point curve) -> Point curve)
-> Maybe (Point curve) -> Point curve
forall a b. (a -> b) -> a -> b
$ do
            Integer
lambda <- Integer -> Integer -> Integer -> Maybe Integer
divmod (Integer
3 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
xp Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
a) (Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
yp) Integer
pr
            let xr :: Integer
xr = (Integer
lambda Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
xp) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
pr
                yr :: Integer
yr = (Integer
lambda Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
xp Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
xr) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
yp) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
pr
            Point curve -> Maybe (Point curve)
forall (m :: * -> *) a. Monad m => a -> m a
return (Point curve -> Maybe (Point curve))
-> Point curve -> Maybe (Point curve)
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Point curve
forall curve. Integer -> Integer -> Point curve
Point Integer
xr Integer
yr
        CurveBinary (CurveBinaryParam Integer
fx)
            | Integer
xp Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0    -> Point curve
forall curve. Point curve
PointO
            | Bool
otherwise  -> Point curve -> Maybe (Point curve) -> Point curve
forall a. a -> Maybe a -> a
fromMaybe Point curve
forall curve. Point curve
PointO (Maybe (Point curve) -> Point curve)
-> Maybe (Point curve) -> Point curve
forall a b. (a -> b) -> a -> b
$ do
                Integer
s <- Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Maybe Integer)
-> (Integer -> Integer) -> Integer -> Maybe Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer -> Integer
addF2m Integer
xp (Integer -> Maybe Integer) -> Maybe Integer -> Maybe Integer
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Integer -> Integer -> Integer -> Maybe Integer
divF2m Integer
fx Integer
yp Integer
xp
                let xr :: Integer
xr = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
s Integer
s Integer -> Integer -> Integer
`addF2m` Integer
s Integer -> Integer -> Integer
`addF2m` Integer
a
                    yr :: Integer
yr = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
xp Integer
xp Integer -> Integer -> Integer
`addF2m` Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
xr (Integer
s Integer -> Integer -> Integer
`addF2m` Integer
1)
                Point curve -> Maybe (Point curve)
forall (m :: * -> *) a. Monad m => a -> m a
return (Point curve -> Maybe (Point curve))
-> Point curve -> Maybe (Point curve)
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Point curve
forall curve. Integer -> Integer -> Point curve
Point Integer
xr Integer
yr
  where
    ty :: CurveType
ty = Point curve -> CurveType
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType Point curve
point
    cc :: CurveParameters curve
cc = Point curve -> CurveParameters curve
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters Point curve
point
    a :: Integer
a  = CurveParameters curve -> Integer
forall curve. CurveParameters curve -> Integer
curveEccA CurveParameters curve
cc

-- | Elliptic curve point multiplication using the base
--
-- /WARNING:/ Vulnerable to timing attacks.
pointBaseMul :: Curve curve => Scalar curve -> Point curve
pointBaseMul :: Scalar curve -> Point curve
pointBaseMul Scalar curve
n = Scalar curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul Scalar curve
n (CurveParameters curve -> Point curve
forall curve. CurveParameters curve -> Point curve
curveEccG (CurveParameters curve -> Point curve)
-> CurveParameters curve -> Point curve
forall a b. (a -> b) -> a -> b
$ Proxy curve -> CurveParameters curve
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters (forall curve. Proxy curve
forall k (t :: k). Proxy t
Proxy :: Proxy curve))

-- | Elliptic curve point multiplication (double and add algorithm).
--
-- /WARNING:/ Vulnerable to timing attacks.
pointMul :: Curve curve => Scalar curve -> Point curve -> Point curve
pointMul :: Scalar curve -> Point curve -> Point curve
pointMul Scalar curve
_ Point curve
PointO = Point curve
forall curve. Point curve
PointO
pointMul (Scalar Integer
n) Point curve
p
    | Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0    = Point curve
forall curve. Point curve
PointO
    | Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
1    = Point curve
p
    | Integer -> Bool
forall a. Integral a => a -> Bool
odd Integer
n     = Point curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p (Scalar curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul (Integer -> Scalar curve
forall curve. Integer -> Scalar curve
Scalar (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)) Point curve
p)
    | Bool
otherwise = Scalar curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul (Integer -> Scalar curve
forall curve. Integer -> Scalar curve
Scalar (Integer
n Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2)) (Point curve -> Point curve
forall curve. Curve curve => Point curve -> Point curve
pointDouble Point curve
p)

-- | Elliptic curve double-scalar multiplication (uses Shamir's trick).
--
-- > pointAddTwoMuls n1 p1 n2 p2 == pointAdd (pointMul n1 p1)
-- >                                         (pointMul n2 p2)
--
-- /WARNING:/ Vulnerable to timing attacks.
pointAddTwoMuls :: Curve curve => Scalar curve -> Point curve -> Scalar curve -> Point curve -> Point curve
pointAddTwoMuls :: Scalar curve
-> Point curve -> Scalar curve -> Point curve -> Point curve
pointAddTwoMuls Scalar curve
_  Point curve
PointO Scalar curve
_  Point curve
PointO = Point curve
forall curve. Point curve
PointO
pointAddTwoMuls Scalar curve
_  Point curve
PointO Scalar curve
n2 Point curve
p2     = Scalar curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul Scalar curve
n2 Point curve
p2
pointAddTwoMuls Scalar curve
n1 Point curve
p1     Scalar curve
_  Point curve
PointO = Scalar curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul Scalar curve
n1 Point curve
p1
pointAddTwoMuls (Scalar Integer
n1) Point curve
p1 (Scalar Integer
n2) Point curve
p2 = (Integer, Integer) -> Point curve
forall a a. (Integral a, Integral a) => (a, a) -> Point curve
go (Integer
n1, Integer
n2)
  where
    p0 :: Point curve
p0 = Point curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p1 Point curve
p2

    go :: (a, a) -> Point curve
go (a
0,  a
0 ) = Point curve
forall curve. Point curve
PointO
    go (a
k1, a
k2) =
        let q :: Point curve
q = Point curve -> Point curve
forall curve. Curve curve => Point curve -> Point curve
pointDouble (Point curve -> Point curve) -> Point curve -> Point curve
forall a b. (a -> b) -> a -> b
$ (a, a) -> Point curve
go (a
k1 a -> a -> a
forall a. Integral a => a -> a -> a
`div` a
2, a
k2 a -> a -> a
forall a. Integral a => a -> a -> a
`div` a
2)
        in case (a -> Bool
forall a. Integral a => a -> Bool
odd a
k1, a -> Bool
forall a. Integral a => a -> Bool
odd a
k2) of
            (Bool
True  , Bool
True  ) -> Point curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p0 Point curve
q
            (Bool
True  , Bool
False ) -> Point curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p1 Point curve
q
            (Bool
False , Bool
True  ) -> Point curve -> Point curve -> Point curve
forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p2 Point curve
q
            (Bool
False , Bool
False ) -> Point curve
q

-- | Check if a point is the point at infinity.
isPointAtInfinity :: Point curve -> Bool
isPointAtInfinity :: Point curve -> Bool
isPointAtInfinity Point curve
PointO = Bool
True
isPointAtInfinity Point curve
_      = Bool
False

-- | Make a point on a curve from integer (x,y) coordinate
--
-- if the point is not valid related to the curve then an error is
-- returned instead of a point
pointFromIntegers :: forall curve . Curve curve => (Integer, Integer) -> CryptoFailable (Point curve)
pointFromIntegers :: (Integer, Integer) -> CryptoFailable (Point curve)
pointFromIntegers (Integer
x,Integer
y)
    | Proxy curve -> Integer -> Integer -> Bool
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> Integer -> Integer -> Bool
isPointValid (Proxy curve
forall k (t :: k). Proxy t
Proxy :: Proxy curve) Integer
x Integer
y = Point curve -> CryptoFailable (Point curve)
forall a. a -> CryptoFailable a
CryptoPassed (Point curve -> CryptoFailable (Point curve))
-> Point curve -> CryptoFailable (Point curve)
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Point curve
forall curve. Integer -> Integer -> Point curve
Point Integer
x Integer
y
    | Bool
otherwise                               = CryptoError -> CryptoFailable (Point curve)
forall a. CryptoError -> CryptoFailable a
CryptoFailed (CryptoError -> CryptoFailable (Point curve))
-> CryptoError -> CryptoFailable (Point curve)
forall a b. (a -> b) -> a -> b
$ CryptoError
CryptoError_PointCoordinatesInvalid

-- | check if a point is on specific curve
--
-- This perform three checks:
--
-- * x is not out of range
-- * y is not out of range
-- * the equation @y^2 = x^3 + a*x + b (mod p)@ holds
isPointValid :: Curve curve => proxy curve -> Integer -> Integer -> Bool
isPointValid :: proxy curve -> Integer -> Integer -> Bool
isPointValid proxy curve
proxy Integer
x Integer
y =
    case CurveType
ty of
        CurvePrime (CurvePrimeParam Integer
p) ->
            let a :: Integer
a  = CurveParameters curve -> Integer
forall curve. CurveParameters curve -> Integer
curveEccA CurveParameters curve
cc
                b :: Integer
b  = CurveParameters curve -> Integer
forall curve. CurveParameters curve -> Integer
curveEccB CurveParameters curve
cc
                eqModP :: Integer -> Integer -> Bool
eqModP Integer
z1 Integer
z2 = (Integer
z1 Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
p) Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== (Integer
z2 Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
p)
                isValid :: Integer -> Bool
isValid Integer
e = Integer
e Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 Bool -> Bool -> Bool
&& Integer
e Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
p
             in Integer -> Bool
isValid Integer
x Bool -> Bool -> Bool
&& Integer -> Bool
isValid Integer
y Bool -> Bool -> Bool
&& (Integer
y Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2 :: Int)) Integer -> Integer -> Bool
`eqModP` (Integer
x Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
3 :: Int) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
b)
        CurveBinary (CurveBinaryParam Integer
fx) ->
            let a :: Integer
a  = CurveParameters curve -> Integer
forall curve. CurveParameters curve -> Integer
curveEccA CurveParameters curve
cc
                b :: Integer
b  = CurveParameters curve -> Integer
forall curve. CurveParameters curve -> Integer
curveEccB CurveParameters curve
cc
                add :: Integer -> Integer -> Integer
add = Integer -> Integer -> Integer
addF2m
                mul :: Integer -> Integer -> Integer
mul = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx
                isValid :: Integer -> Bool
isValid Integer
e = Integer -> Integer -> Integer
modF2m Integer
fx Integer
e Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
e
             in [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ Integer -> Bool
isValid Integer
x
                    , Integer -> Bool
isValid Integer
y
                    , ((((Integer
x Integer -> Integer -> Integer
`add` Integer
a) Integer -> Integer -> Integer
`mul` Integer
x Integer -> Integer -> Integer
`add` Integer
y) Integer -> Integer -> Integer
`mul` Integer
x) Integer -> Integer -> Integer
`add` Integer
b Integer -> Integer -> Integer
`add` (Integer -> Integer -> Integer
squareF2m Integer
fx Integer
y)) Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0
                    ]
  where
    ty :: CurveType
ty = proxy curve -> CurveType
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType proxy curve
proxy
    cc :: CurveParameters curve
cc = proxy curve -> CurveParameters curve
forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters proxy curve
proxy

-- | div and mod
divmod :: Integer -> Integer -> Integer -> Maybe Integer
divmod :: Integer -> Integer -> Integer -> Maybe Integer
divmod Integer
y Integer
x Integer
m = do
    Integer
i <- Integer -> Integer -> Maybe Integer
inverse (Integer
x Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
m) Integer
m
    Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Maybe Integer) -> Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ Integer
y Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
m