-- | Elliptic Curve Arithmetic.
--
-- /WARNING:/ These functions are vulnerable to timing attacks.
module Crypto.PubKey.ECC.Prim ( pointAdd , pointDouble , pointMul ) where import Data.Maybe import Crypto.Number.ModArithmetic import Crypto.Number.F2m import Crypto.Types.PubKey.ECC
-- | Elliptic Curve point addition.
--
-- /WARNING:/ Vulnerable to timing attacks.
pointAdd
::
Curve
->
Point
->
Point
->
Point
pointAdd
_
PointO
PointO
=
PointO
pointAdd
_
PointO
q
=
q
pointAdd
_
p
PointO
=
p
pointAdd
c
@(
CurveFP
(
CurvePrime
pr
_))
p
@(
Point
xp
yp
)
q
@(
Point
xq
yq
) |
p
==
Point
xq
(-
yq
) =
PointO
|
p
==
q
=
pointDouble
c
p
|
otherwise
= let
s
=
divmod
(
yp
-
yq
) (
xp
-
xq
)
pr
xr
= (
s
^
(
2
::
Int
)
-
xp
-
xq
)
`mod`
pr
yr
= (
s
*
(
xp
-
xr
)
-
yp
)
`mod`
pr
in
Point
xr
yr
pointAdd
c
@(
CurveF2m
(
CurveBinary
fx
cc
))
p
@(
Point
xp
yp
)
q
@(
Point
xq
yq
) |
p
==
Point
xq
(
xq
`addF2m`
yq
) =
PointO
|
p
==
q
=
pointDouble
c
p
|
otherwise
=
fromMaybe
PointO
$
do
s
<-
divF2m
fx
(
yp
`addF2m`
yq
) (
xp
`addF2m`
xq
) let
xr
=
mulF2m
fx
s
s
`addF2m`
s
`addF2m`
xp
`addF2m`
xq
`addF2m`
a
yr
=
mulF2m
fx
s
(
xp
`addF2m`
xr
)
`addF2m`
xr
`addF2m`
yp
return
$
Point
xr
yr
where
a
=
ecc_a
cc
-- | Elliptic Curve point doubling.
--
-- /WARNING:/ Vulnerable to timing attacks.
pointDouble
::
Curve
->
Point
->
Point
pointDouble
_
PointO
=
PointO
pointDouble
(
CurveFP
(
CurvePrime
pr
cc
)) (
Point
xp
yp
) = let
l
=
divmod
(
3
*
xp
^
(
2
::
Int
)
+
a
) (
2
*
yp
)
pr
xr
= (
l
^
(
2
::
Int
)
-
2
*
xp
)
`mod`
pr
yr
= (
l
*
(
xp
-
xr
)
-
yp
)
`mod`
pr
in
Point
xr
yr
where
a
=
ecc_a
cc
pointDouble
(
CurveF2m
(
CurveBinary
fx
cc
)) (
Point
xp
yp
) =
fromMaybe
PointO
$
do
s
<-
return
.
addF2m
xp
=<<
divF2m
fx
yp
xp
let
xr
=
mulF2m
fx
s
s
`addF2m`
s
`addF2m`
a
yr
=
mulF2m
fx
xp
xp
`addF2m`
mulF2m
fx
xr
(
s
`addF2m`
1
)
return
$
Point
xr
yr
where
a
=
ecc_a
cc
-- | Elliptic curve point multiplication (double and add algorithm).
--
-- /WARNING:/ Vulnerable to timing attacks.
pointMul
::
Curve
->
Integer
->
Point
->
Point
pointMul
c
n
p
|
n
==
1
=
p
|
odd
n
=
pointAdd
c
p
(
pointMul
c
(
n
-
1
)
p
) |
otherwise
=
pointMul
c
(
n
`div`
2
) (
pointDouble
c
p
)
-- | div and mod
divmod
::
Integer
->
Integer
->
Integer
->
Integer
divmod
y
x
m
=
y
*
fromJust
(
inverse
(
x
`mod`
m
)
m
)
`mod`
m