{-# LANGUAGE BangPatterns #-}
module Crypto.Internal.ECC (
MulResult (..),
CurveField (..),
curveMul,
primeCurveMul,
primeCurveTableMul,
baseTable,
binaryCurveMul,
binaryCurveC,
) where
import Crypto.Internal.Compat (unsafeDoIO)
import Crypto.Number.Basic (numBits, numBytes)
import Crypto.Number.F2m (addF2m, divF2m, mulF2m, squareF2m)
import qualified Crypto.Number.Serialize.Internal as Internal
import Crypto.PubKey.ECC.Types (
Curve (..),
CurveCommon (..),
CurveName,
CurvePrime (..),
Point (..),
getCurveByName,
)
import Data.Bits (testBit)
import Data.Word (Word32, Word8)
import Foreign.C.Types (CInt (..))
import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrBytes, withForeignPtr)
import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.Ptr (Ptr, plusPtr)
data MulResult
=
MulPoint !Integer !Integer
|
MulInfinity
|
MulUnsupported
deriving (Int -> MulResult -> ShowS
[MulResult] -> ShowS
MulResult -> String
(Int -> MulResult -> ShowS)
-> (MulResult -> String)
-> ([MulResult] -> ShowS)
-> Show MulResult
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MulResult -> ShowS
showsPrec :: Int -> MulResult -> ShowS
$cshow :: MulResult -> String
show :: MulResult -> String
$cshowList :: [MulResult] -> ShowS
showList :: [MulResult] -> ShowS
Show, MulResult -> MulResult -> Bool
(MulResult -> MulResult -> Bool)
-> (MulResult -> MulResult -> Bool) -> Eq MulResult
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MulResult -> MulResult -> Bool
== :: MulResult -> MulResult -> Bool
$c/= :: MulResult -> MulResult -> Bool
/= :: MulResult -> MulResult -> Bool
Eq)
primeCurveMul
:: Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Integer
-> MulResult
primeCurveMul :: Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Integer
-> MulResult
primeCurveMul Integer
p Integer
a Integer
b Int
klen Integer
k Integer
px Integer
py
| Integer
p Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0 Bool -> Bool -> Bool
|| Integer -> Bool
forall a. Integral a => a -> Bool
even Integer
p Bool -> Bool -> Bool
|| Int
klen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = MulResult
MulUnsupported
| Bool
otherwise = IO MulResult -> MulResult
forall a. IO a -> a
unsafeDoIO (IO MulResult -> MulResult) -> IO MulResult -> MulResult
forall a b. (a -> b) -> a -> b
$
Int -> (Ptr Word8 -> IO MulResult) -> IO MulResult
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
widths) ((Ptr Word8 -> IO MulResult) -> IO MulResult)
-> (Ptr Word8 -> IO MulResult) -> IO MulResult
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
base -> case (Ptr Word8 -> Int -> Ptr Word8)
-> Ptr Word8 -> [Int] -> [Ptr Word8]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
base [Int]
widths of
(Ptr Word8
outx : Ptr Word8
outy : Ptr Word8
cx : Ptr Word8
cy : Ptr Word8
ca : Ptr Word8
cb : Ptr Word8
cp : Ptr Word8
ck : [Ptr Word8]
_) -> do
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
px Ptr Word8
cx Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
py Ptr Word8
cy Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
a Ptr Word8
ca Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
b Ptr Word8
cb Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
p Ptr Word8
cp Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
k Ptr Word8
ck Int
klen
CInt
r <-
Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO CInt
c_ecc_mul
Ptr Word8
outx
Ptr Word8
outy
Ptr Word8
cx
Ptr Word8
cy
Ptr Word8
ck
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
klen)
Ptr Word8
ca
Ptr Word8
cb
Ptr Word8
cp
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
plen)
Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
0 Ptr Word8
ck Int
klen IO Int -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
case CInt
r of
CInt
0 -> do
!Integer
x <- Ptr Word8 -> Int -> IO Integer
Internal.os2ip Ptr Word8
outx Int
plen
!Integer
y <- Ptr Word8 -> Int -> IO Integer
Internal.os2ip Ptr Word8
outy Int
plen
MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Integer -> MulResult
MulPoint Integer
x Integer
y)
CInt
1 -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulInfinity
CInt
_ -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulUnsupported
[Ptr Word8]
_ -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulUnsupported
where
!plen :: Int
plen = Integer -> Int
numBytes Integer
p
widths :: [Int]
widths = [Int
plen, Int
plen, Int
plen, Int
plen, Int
plen, Int
plen, Int
plen, Int
klen]
foreign import ccall unsafe "crypton_ecc_table_size"
c_ecc_table_size :: Word32 -> Word32 -> Word32
foreign import ccall safe "crypton_ecc_table_build"
c_ecc_table_build
:: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO CInt
foreign import ccall safe "crypton_ecc_table_mul"
c_ecc_table_mul
:: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO CInt
foreign import ccall safe "crypton_ecc_mul"
c_ecc_mul
:: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO CInt
data CurveField
=
Prime !Integer !Integer !Integer
|
Binary !Integer !Integer
deriving (Int -> CurveField -> ShowS
[CurveField] -> ShowS
CurveField -> String
(Int -> CurveField -> ShowS)
-> (CurveField -> String)
-> ([CurveField] -> ShowS)
-> Show CurveField
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CurveField -> ShowS
showsPrec :: Int -> CurveField -> ShowS
$cshow :: CurveField -> String
show :: CurveField -> String
$cshowList :: [CurveField] -> ShowS
showList :: [CurveField] -> ShowS
Show, CurveField -> CurveField -> Bool
(CurveField -> CurveField -> Bool)
-> (CurveField -> CurveField -> Bool) -> Eq CurveField
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CurveField -> CurveField -> Bool
== :: CurveField -> CurveField -> Bool
$c/= :: CurveField -> CurveField -> Bool
/= :: CurveField -> CurveField -> Bool
Eq)
curveMul
:: CurveField
-> Integer
-> Integer
-> Integer
-> Integer
-> Bool
-> MulResult
curveMul :: CurveField
-> Integer -> Integer -> Integer -> Integer -> Bool -> MulResult
curveMul CurveField
field Integer
order Integer
k Integer
px Integer
py Bool
isBase = case CurveField
field of
Prime Integer
p Integer
a Integer
b
| Bool
isBase
, Int
klen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Integer -> Int
numBytes Integer
order
, Just ForeignPtr Word8
table <- Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Maybe (ForeignPtr Word8)
baseTable Integer
p Integer
a Integer
b Int
klen Integer
px Integer
py ->
ForeignPtr Word8
-> Integer -> Integer -> Integer -> Int -> Integer -> MulResult
primeCurveTableMul ForeignPtr Word8
table Integer
p Integer
a Integer
b Int
klen Integer
k
| Bool
otherwise -> Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Integer
-> MulResult
primeCurveMul Integer
p Integer
a Integer
b Int
klen Integer
k Integer
px Integer
py
Binary Integer
fx Integer
b
| Integer
px Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 -> MulResult
MulUnsupported
| Bool
otherwise -> case Integer
-> Integer -> Int -> Integer -> Integer -> Integer -> MulResult
binaryCurveC Integer
fx Integer
b Int
klen Integer
k Integer
px Integer
py of
MulResult
MulUnsupported -> Integer
-> Integer -> Int -> Integer -> Integer -> Integer -> MulResult
binaryCurveMul Integer
fx Integer
b (Int
klen Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8) Integer
k Integer
px Integer
py
MulResult
r -> MulResult
r
where
!klen :: Int
klen = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Integer -> Int
numBytes Integer
k) (Integer -> Int
numBytes Integer
order)
baseTable
:: Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Maybe (ForeignPtr Word8)
baseTable :: Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Maybe (ForeignPtr Word8)
baseTable Integer
p Integer
a Integer
b Int
klen Integer
gx Integer
gy =
case (Integer, Integer, Integer, Int, Integer, Integer)
-> [((Integer, Integer, Integer, Int, Integer, Integer),
Maybe (ForeignPtr Word8))]
-> Maybe (Maybe (ForeignPtr Word8))
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (Integer
p, Integer
a, Integer
b, Int
klen, Integer
gx, Integer
gy) [((Integer, Integer, Integer, Int, Integer, Integer),
Maybe (ForeignPtr Word8))]
baseTables of
Just Maybe (ForeignPtr Word8)
table -> Maybe (ForeignPtr Word8)
table
Maybe (Maybe (ForeignPtr Word8))
Nothing -> Maybe (ForeignPtr Word8)
forall a. Maybe a
Nothing
type TableKey = (Integer, Integer, Integer, Int, Integer, Integer)
baseTables :: [(TableKey, Maybe (ForeignPtr Word8))]
baseTables :: [((Integer, Integer, Integer, Int, Integer, Integer),
Maybe (ForeignPtr Word8))]
baseTables =
[ ((Integer
p, Integer
a, Integer
b, Int
klen, Integer
gx, Integer
gy), Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Maybe (ForeignPtr Word8)
primeCurveTable Integer
p Integer
a Integer
b Int
klen Integer
gx Integer
gy)
| CurveName
name <- [CurveName
forall a. Bounded a => a
minBound .. CurveName
forall a. Bounded a => a
maxBound] :: [CurveName]
, CurveFP (CurvePrime Integer
p CurveCommon
cc) <- [CurveName -> Curve
getCurveByName CurveName
name]
, Point Integer
gx Integer
gy <- [CurveCommon -> Point
ecc_g CurveCommon
cc]
, let a :: Integer
a = CurveCommon -> Integer
ecc_a CurveCommon
cc
, let b :: Integer
b = CurveCommon -> Integer
ecc_b CurveCommon
cc
, let klen :: Int
klen = Integer -> Int
numBytes (CurveCommon -> Integer
ecc_n CurveCommon
cc)
]
{-# NOINLINE baseTables #-}
primeCurveTable
:: Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Maybe (ForeignPtr Word8)
primeCurveTable :: Integer
-> Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Maybe (ForeignPtr Word8)
primeCurveTable Integer
p Integer
a Integer
b Int
klen Integer
px Integer
py
| Integer
p Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0 Bool -> Bool -> Bool
|| Integer -> Bool
forall a. Integral a => a -> Bool
even Integer
p Bool -> Bool -> Bool
|| Int
klen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Word32
size Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0 = Maybe (ForeignPtr Word8)
forall a. Maybe a
Nothing
| Bool
otherwise = IO (Maybe (ForeignPtr Word8)) -> Maybe (ForeignPtr Word8)
forall a. IO a -> a
unsafeDoIO (IO (Maybe (ForeignPtr Word8)) -> Maybe (ForeignPtr Word8))
-> IO (Maybe (ForeignPtr Word8)) -> Maybe (ForeignPtr Word8)
forall a b. (a -> b) -> a -> b
$ do
ForeignPtr Word8
table <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
size)
Int
-> (Ptr Word8 -> IO (Maybe (ForeignPtr Word8)))
-> IO (Maybe (ForeignPtr Word8))
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
widths) ((Ptr Word8 -> IO (Maybe (ForeignPtr Word8)))
-> IO (Maybe (ForeignPtr Word8)))
-> (Ptr Word8 -> IO (Maybe (ForeignPtr Word8)))
-> IO (Maybe (ForeignPtr Word8))
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
base -> case (Ptr Word8 -> Int -> Ptr Word8)
-> Ptr Word8 -> [Int] -> [Ptr Word8]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
base [Int]
widths of
(Ptr Word8
cx : Ptr Word8
cy : Ptr Word8
ca : Ptr Word8
cb : Ptr Word8
cp : [Ptr Word8]
_) -> do
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
px Ptr Word8
cx Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
py Ptr Word8
cy Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
a Ptr Word8
ca Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
b Ptr Word8
cb Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
p Ptr Word8
cp Int
plen
CInt
r <- ForeignPtr Word8 -> (Ptr Word8 -> IO CInt) -> IO CInt
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
table ((Ptr Word8 -> IO CInt) -> IO CInt)
-> (Ptr Word8 -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
t ->
Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO CInt
c_ecc_table_build
Ptr Word8
t
Ptr Word8
cx
Ptr Word8
cy
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
klen)
Ptr Word8
ca
Ptr Word8
cb
Ptr Word8
cp
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
plen)
Maybe (ForeignPtr Word8) -> IO (Maybe (ForeignPtr Word8))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (ForeignPtr Word8) -> IO (Maybe (ForeignPtr Word8)))
-> Maybe (ForeignPtr Word8) -> IO (Maybe (ForeignPtr Word8))
forall a b. (a -> b) -> a -> b
$ if CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0 then ForeignPtr Word8 -> Maybe (ForeignPtr Word8)
forall a. a -> Maybe a
Just ForeignPtr Word8
table else Maybe (ForeignPtr Word8)
forall a. Maybe a
Nothing
[Ptr Word8]
_ -> Maybe (ForeignPtr Word8) -> IO (Maybe (ForeignPtr Word8))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (ForeignPtr Word8)
forall a. Maybe a
Nothing
where
!plen :: Int
plen = Integer -> Int
numBytes Integer
p
!size :: Word32
size = Word32 -> Word32 -> Word32
c_ecc_table_size (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
plen) (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
klen)
widths :: [Int]
widths = [Int
plen, Int
plen, Int
plen, Int
plen, Int
plen]
primeCurveTableMul
:: ForeignPtr Word8
-> Integer
-> Integer
-> Integer
-> Int
-> Integer
-> MulResult
primeCurveTableMul :: ForeignPtr Word8
-> Integer -> Integer -> Integer -> Int -> Integer -> MulResult
primeCurveTableMul ForeignPtr Word8
table Integer
p Integer
a Integer
b Int
klen Integer
k
| Integer
p Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0 Bool -> Bool -> Bool
|| Integer -> Bool
forall a. Integral a => a -> Bool
even Integer
p Bool -> Bool -> Bool
|| Int
klen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = MulResult
MulUnsupported
| Bool
otherwise = IO MulResult -> MulResult
forall a. IO a -> a
unsafeDoIO (IO MulResult -> MulResult) -> IO MulResult -> MulResult
forall a b. (a -> b) -> a -> b
$
Int -> (Ptr Word8 -> IO MulResult) -> IO MulResult
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
widths) ((Ptr Word8 -> IO MulResult) -> IO MulResult)
-> (Ptr Word8 -> IO MulResult) -> IO MulResult
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
base -> case (Ptr Word8 -> Int -> Ptr Word8)
-> Ptr Word8 -> [Int] -> [Ptr Word8]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
base [Int]
widths of
(Ptr Word8
outx : Ptr Word8
outy : Ptr Word8
ca : Ptr Word8
cb : Ptr Word8
cp : Ptr Word8
ck : [Ptr Word8]
_) -> do
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
a Ptr Word8
ca Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
b Ptr Word8
cb Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
p Ptr Word8
cp Int
plen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
k Ptr Word8
ck Int
klen
CInt
r <- ForeignPtr Word8 -> (Ptr Word8 -> IO CInt) -> IO CInt
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
table ((Ptr Word8 -> IO CInt) -> IO CInt)
-> (Ptr Word8 -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
t ->
Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> IO CInt
c_ecc_table_mul
Ptr Word8
outx
Ptr Word8
outy
Ptr Word8
t
Ptr Word8
ck
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
klen)
Ptr Word8
ca
Ptr Word8
cb
Ptr Word8
cp
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
plen)
Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
0 Ptr Word8
ck Int
klen IO Int -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
case CInt
r of
CInt
0 -> do
!Integer
x <- Ptr Word8 -> Int -> IO Integer
Internal.os2ip Ptr Word8
outx Int
plen
!Integer
y <- Ptr Word8 -> Int -> IO Integer
Internal.os2ip Ptr Word8
outy Int
plen
MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Integer -> MulResult
MulPoint Integer
x Integer
y)
CInt
1 -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulInfinity
CInt
_ -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulUnsupported
[Ptr Word8]
_ -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulUnsupported
where
!plen :: Int
plen = Integer -> Int
numBytes Integer
p
widths :: [Int]
widths = [Int
plen, Int
plen, Int
plen, Int
plen, Int
plen, Int
klen]
binaryCurveMul
:: Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Integer
-> MulResult
binaryCurveMul :: Integer
-> Integer -> Int -> Integer -> Integer -> Integer -> MulResult
binaryCurveMul Integer
fx Integer
b Int
bits Integer
k Integer
x Integer
y
| Int
bits Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 Bool -> Bool -> Bool
|| Integer
x Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = MulResult
MulUnsupported
| Bool
otherwise = ((Integer, Integer), (Integer, Integer)) -> MulResult
recover (Int
-> (Integer, Integer)
-> (Integer, Integer)
-> ((Integer, Integer), (Integer, Integer))
go (Int
bits Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Integer
1, Integer
0) (Integer
x, Integer
1))
where
infixl 6 .+.
.+. :: Integer -> Integer -> Integer
(.+.) = Integer -> Integer -> Integer
addF2m
sqr :: Integer -> Integer
sqr = Integer -> Integer -> Integer
squareF2m Integer
fx
mul :: Integer -> Integer -> Integer
mul = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx
madd :: (Integer, Integer) -> (Integer, Integer) -> (Integer, Integer)
madd (Integer
xa, Integer
za) (Integer
xb, Integer
zb) =
let t1 :: Integer
t1 = Integer -> Integer -> Integer
mul Integer
xa Integer
zb
t2 :: Integer
t2 = Integer -> Integer -> Integer
mul Integer
xb Integer
za
z :: Integer
z = Integer -> Integer
sqr (Integer
t1 Integer -> Integer -> Integer
.+. Integer
t2)
in (Integer -> Integer -> Integer
mul Integer
x Integer
z Integer -> Integer -> Integer
.+. Integer -> Integer -> Integer
mul Integer
t1 Integer
t2, Integer
z)
mdouble :: (Integer, Integer) -> (Integer, Integer)
mdouble (Integer
xa, Integer
za) =
let xa2 :: Integer
xa2 = Integer -> Integer
sqr Integer
xa
za2 :: Integer
za2 = Integer -> Integer
sqr Integer
za
in (Integer -> Integer
sqr Integer
xa2 Integer -> Integer -> Integer
.+. Integer -> Integer -> Integer
mul Integer
b (Integer -> Integer
sqr Integer
za2), Integer -> Integer -> Integer
mul Integer
xa2 Integer
za2)
go :: Int
-> (Integer, Integer)
-> (Integer, Integer)
-> ((Integer, Integer), (Integer, Integer))
go Int
i (Integer, Integer)
p1 (Integer, Integer)
p2
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = ((Integer, Integer)
p1, (Integer, Integer)
p2)
| Integer -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Integer
k Int
i =
let !s :: (Integer, Integer)
s = (Integer, Integer) -> (Integer, Integer) -> (Integer, Integer)
madd (Integer, Integer)
p1 (Integer, Integer)
p2
!d :: (Integer, Integer)
d = (Integer, Integer) -> (Integer, Integer)
mdouble (Integer, Integer)
p2
in Int
-> (Integer, Integer)
-> (Integer, Integer)
-> ((Integer, Integer), (Integer, Integer))
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Integer, Integer)
s (Integer, Integer)
d
| Bool
otherwise =
let !s :: (Integer, Integer)
s = (Integer, Integer) -> (Integer, Integer) -> (Integer, Integer)
madd (Integer, Integer)
p1 (Integer, Integer)
p2
!d :: (Integer, Integer)
d = (Integer, Integer) -> (Integer, Integer)
mdouble (Integer, Integer)
p1
in Int
-> (Integer, Integer)
-> (Integer, Integer)
-> ((Integer, Integer), (Integer, Integer))
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Integer, Integer)
d (Integer, Integer)
s
recover :: ((Integer, Integer), (Integer, Integer)) -> MulResult
recover ((Integer
x1, Integer
z1), (Integer
x2, Integer
z2))
| Integer
z1 Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = MulResult
MulInfinity
| Integer
z2 Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = Integer -> Integer -> MulResult
MulPoint Integer
x (Integer
x Integer -> Integer -> Integer
.+. Integer
y)
| Bool
otherwise = case (Integer -> Integer -> Integer -> Maybe Integer
divF2m Integer
fx Integer
x1 Integer
z1, Integer -> Integer -> Integer -> Maybe Integer
divF2m Integer
fx Integer
x2 Integer
z2) of
(Just Integer
xa, Just Integer
xb) ->
let u :: Integer
u = Integer
xa Integer -> Integer -> Integer
.+. Integer
x
v :: Integer
v = Integer
xb Integer -> Integer -> Integer
.+. Integer
x
inner :: Integer
inner = Integer -> Integer -> Integer
mul Integer
u Integer
v Integer -> Integer -> Integer
.+. Integer -> Integer
sqr Integer
x Integer -> Integer -> Integer
.+. Integer
y
in case Integer -> Integer -> Integer -> Maybe Integer
divF2m Integer
fx (Integer -> Integer -> Integer
mul Integer
u Integer
inner) Integer
x of
Just Integer
w -> Integer -> Integer -> MulResult
MulPoint Integer
xa (Integer
w Integer -> Integer -> Integer
.+. Integer
y)
Maybe Integer
Nothing -> MulResult
MulUnsupported
(Maybe Integer, Maybe Integer)
_ -> MulResult
MulUnsupported
binaryCurveC
:: Integer
-> Integer
-> Int
-> Integer
-> Integer
-> Integer
-> MulResult
binaryCurveC :: Integer
-> Integer -> Int -> Integer -> Integer -> Integer -> MulResult
binaryCurveC Integer
fx Integer
b Int
klen Integer
k Integer
px Integer
py
| Integer
fx Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
1 Bool -> Bool -> Bool
|| Int
klen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 Bool -> Bool -> Bool
|| Integer
px Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0 Bool -> Bool -> Bool
|| Int
flen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = MulResult
MulUnsupported
| Bool
otherwise = IO MulResult -> MulResult
forall a. IO a -> a
unsafeDoIO (IO MulResult -> MulResult) -> IO MulResult -> MulResult
forall a b. (a -> b) -> a -> b
$
Int -> (Ptr Word8 -> IO MulResult) -> IO MulResult
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
widths) ((Ptr Word8 -> IO MulResult) -> IO MulResult)
-> (Ptr Word8 -> IO MulResult) -> IO MulResult
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
base -> case (Ptr Word8 -> Int -> Ptr Word8)
-> Ptr Word8 -> [Int] -> [Ptr Word8]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
base [Int]
widths of
(Ptr Word8
outx : Ptr Word8
outy : Ptr Word8
cx : Ptr Word8
cy : Ptr Word8
cb : Ptr Word8
cf : Ptr Word8
ck : [Ptr Word8]
_) -> do
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
px Ptr Word8
cx Int
flen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
py Ptr Word8
cy Int
flen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
b Ptr Word8
cb Int
flen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
fx Ptr Word8
cf Int
fxlen
Int
_ <- Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
k Ptr Word8
ck Int
klen
CInt
r <-
Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> IO CInt
c_f2m_mul
Ptr Word8
outx
Ptr Word8
outy
Ptr Word8
cx
Ptr Word8
cy
Ptr Word8
ck
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
klen)
Ptr Word8
cb
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
flen)
Ptr Word8
cf
(Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
fxlen)
Integer -> Ptr Word8 -> Int -> IO Int
Internal.i2ospOf Integer
0 Ptr Word8
ck Int
klen IO Int -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
case CInt
r of
CInt
0 -> do
!Integer
x <- Ptr Word8 -> Int -> IO Integer
Internal.os2ip Ptr Word8
outx Int
flen
!Integer
y <- Ptr Word8 -> Int -> IO Integer
Internal.os2ip Ptr Word8
outy Int
flen
MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Integer -> MulResult
MulPoint Integer
x Integer
y)
CInt
1 -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulInfinity
CInt
_ -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulUnsupported
[Ptr Word8]
_ -> MulResult -> IO MulResult
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MulResult
MulUnsupported
where
!flen :: Int
flen = (Integer -> Int
numBits Integer
fx Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
7) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
8
!fxlen :: Int
fxlen = Integer -> Int
numBytes Integer
fx
widths :: [Int]
widths = [Int
flen, Int
flen, Int
flen, Int
flen, Int
flen, Int
fxlen, Int
klen]
foreign import ccall safe "crypton_f2m_mul"
c_f2m_mul
:: Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> Ptr Word8
-> Word32
-> IO CInt