diff --git a/Benchs/Bench.hs b/Benchs/Bench.hs
--- a/Benchs/Bench.hs
+++ b/Benchs/Bench.hs
@@ -36,46 +36,50 @@
         ecdsaSignatureP = fst $ ECDSA.sign rng ecdsaPrivatekeyP SHA1.hash bs
         ecdsaSignatureB = fst $ ECDSA.sign rng ecdsaPrivatekeyB SHA1.hash bs
     defaultMain
-        [ bgroup "RSA PKCS15"
-            [ bench "encryption" $ nf (right . fst . PKCS15.encrypt rng rsaPublickey) bs
-            , bgroup "decryption"
-                [ bench "slow" $ nf (right . PKCS15.decrypt Nothing privateKeySlow) encryptedMsgPKCS
-                , bench "fast" $ nf (right . PKCS15.decrypt Nothing rsaPrivatekey) encryptedMsgPKCS
-                , bench "slow+blinding" $ nf (right . PKCS15.decrypt (Just blinder) privateKeySlow) encryptedMsgPKCS
-                , bench "fast+blinding" $ nf (right . PKCS15.decrypt (Just blinder) rsaPrivatekey) encryptedMsgPKCS
+        [ bgroup "RSA"
+            [ bgroup "PKCS15"
+                [ bench "encryption" $ nf (right . fst . PKCS15.encrypt rng rsaPublickey) bs
+                , bgroup "decryption"
+                    [ bench "slow" $ nf (right . PKCS15.decrypt Nothing privateKeySlow) encryptedMsgPKCS
+                    , bench "fast" $ nf (right . PKCS15.decrypt Nothing rsaPrivatekey) encryptedMsgPKCS
+                    , bench "slow+blinding" $ nf (right . PKCS15.decrypt (Just blinder) privateKeySlow) encryptedMsgPKCS
+                    , bench "fast+blinding" $ nf (right . PKCS15.decrypt (Just blinder) rsaPrivatekey) encryptedMsgPKCS
+                    ]
+                , bgroup "signing"
+                    [ bench "slow" $ nf (right . PKCS15.sign Nothing hashDescrSHA1 privateKeySlow) bs
+                    , bench "fast" $ nf (right . PKCS15.sign Nothing hashDescrSHA1 rsaPrivatekey) bs
+                    , bench "slow+blinding" $ nf (right . PKCS15.sign (Just blinder) hashDescrSHA1 privateKeySlow) bs
+                    , bench "fast+blinding" $ nf (right . PKCS15.sign (Just blinder) hashDescrSHA1 rsaPrivatekey) bs
+                    ]
+                , bench "verify" $ nf (PKCS15.verify hashDescrSHA1 rsaPublickey bs) signedMsgPKCS
                 ]
-            , bgroup "signing"
-                [ bench "slow" $ nf (right . PKCS15.sign Nothing hashDescrSHA1 privateKeySlow) bs
-                , bench "fast" $ nf (right . PKCS15.sign Nothing hashDescrSHA1 rsaPrivatekey) bs
-                , bench "slow+blinding" $ nf (right . PKCS15.sign (Just blinder) hashDescrSHA1 privateKeySlow) bs
-                , bench "fast+blinding" $ nf (right . PKCS15.sign (Just blinder) hashDescrSHA1 rsaPrivatekey) bs
+            , bgroup "OAEP"
+                [ bench "encryption" $ nf (right . fst . OAEP.encrypt rng oaepParams rsaPublickey) bs
+                , bgroup "decryption"
+                    [ bench "slow" $ nf (right . OAEP.decrypt Nothing oaepParams privateKeySlow) encryptedMsgOAEP
+                    , bench "fast" $ nf (right . OAEP.decrypt Nothing oaepParams rsaPrivatekey) encryptedMsgOAEP
+                    , bench "slow+blinding" $ nf (right . OAEP.decrypt (Just blinder) oaepParams privateKeySlow) encryptedMsgOAEP
+                    , bench "fast+blinding" $ nf (right . OAEP.decrypt (Just blinder) oaepParams rsaPrivatekey) encryptedMsgOAEP
+                    ]
                 ]
-            , bench "verify" $ nf (PKCS15.verify hashDescrSHA1 rsaPublickey bs) signedMsgPKCS
-            ]
-        , bgroup "RSA OAEP"
-            [ bench "encryption" $ nf (right . fst . OAEP.encrypt rng oaepParams rsaPublickey) bs
-            , bgroup "decryption"
-                [ bench "slow" $ nf (right . OAEP.decrypt Nothing oaepParams privateKeySlow) encryptedMsgOAEP
-                , bench "fast" $ nf (right . OAEP.decrypt Nothing oaepParams rsaPrivatekey) encryptedMsgOAEP
-                , bench "slow+blinding" $ nf (right . OAEP.decrypt (Just blinder) oaepParams privateKeySlow) encryptedMsgOAEP
-                , bench "fast+blinding" $ nf (right . OAEP.decrypt (Just blinder) oaepParams rsaPrivatekey) encryptedMsgOAEP
+            , bgroup "PSS"
+                [ bgroup "signing"
+                    [ bench "slow" $ nf (right . fst . PSS.sign rng Nothing pssParams privateKeySlow) bs
+                    , bench "fast" $ nf (right . fst . PSS.sign rng Nothing pssParams rsaPrivatekey) bs
+                    , bench "slow+blinding" $ nf (right . fst . PSS.sign rng (Just blinder) pssParams privateKeySlow) bs
+                    , bench "fast+blinding" $ nf (right . fst . PSS.sign rng (Just blinder) pssParams rsaPrivatekey) bs
+                    ]
+                , bench "verify" $ nf (PSS.verify pssParams rsaPublickey bs) signedMsgPSS
                 ]
             ]
-        , bgroup "RSA PSS"
-            [ bgroup "signing"
-                [ bench "slow" $ nf (right . fst . PSS.sign rng Nothing pssParams privateKeySlow) bs
-                , bench "fast" $ nf (right . fst . PSS.sign rng Nothing pssParams rsaPrivatekey) bs
-                , bench "slow+blinding" $ nf (right . fst . PSS.sign rng (Just blinder) pssParams privateKeySlow) bs
-                , bench "fast+blinding" $ nf (right . fst . PSS.sign rng (Just blinder) pssParams rsaPrivatekey) bs
+        , bgroup "ECDSA"
+            [ bgroup "secp160r1"
+                [ bench "sign" $ nf (fst . ECDSA.sign rng ecdsaPrivatekeyP SHA1.hash) bs
+                , bench "verify"  $ nf (ECDSA.verify SHA1.hash ecdsaPublickeyP ecdsaSignatureP) bs
                 ]
-            , bench "verify" $ nf (PSS.verify pssParams rsaPublickey bs) signedMsgPSS
-            ]
-        , bgroup "ECDSA secp160r1"
-            [ bench "sign" $ nf (fst . ECDSA.sign rng ecdsaPrivatekeyP SHA1.hash) bs
-            , bench "verify"  $ nf (ECDSA.verify SHA1.hash ecdsaPublickeyP ecdsaSignatureP) bs
-            ]
-        , bgroup "ECDSA sect163k1"
-            [ bench "sign" $ nf (fst . ECDSA.sign rng ecdsaPrivatekeyB SHA1.hash) bs
-            , bench "verify"  $ nf (ECDSA.verify SHA1.hash ecdsaPublickeyB ecdsaSignatureB) bs
+            , bgroup "sect163k1"
+                [ bench "sign" $ nf (fst . ECDSA.sign rng ecdsaPrivatekeyB SHA1.hash) bs
+                , bench "verify"  $ nf (ECDSA.verify SHA1.hash ecdsaPublickeyB ecdsaSignatureB) bs
+                ]
             ]
         ]
diff --git a/Crypto/PubKey/ECC/DH.hs b/Crypto/PubKey/ECC/DH.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/PubKey/ECC/DH.hs
@@ -0,0 +1,36 @@
+module Crypto.PubKey.ECC.DH (
+    Curve
+  , PublicPoint
+  , PrivateNumber
+  , SharedKey(..)
+  , generatePrivate
+  , calculatePublic
+  , getShared
+  ) where
+
+import Crypto.Number.Generate (generateMax)
+import Crypto.PubKey.ECC.Prim (pointMul)
+import Crypto.Random (CPRG)
+import Crypto.Types.PubKey.DH (SharedKey(..))
+import Crypto.Types.PubKey.ECC (PublicPoint, PrivateNumber, Curve, Point(..))
+import Crypto.Types.PubKey.ECC (ecc_n, ecc_g, common_curve)
+
+-- | Generating a private number d.
+generatePrivate :: CPRG g => g -> Curve -> (PrivateNumber, g)
+generatePrivate rng curve = generateMax rng n
+  where
+    n = ecc_n $ common_curve curve
+
+-- | Generating a public point Q.
+calculatePublic :: Curve -> PrivateNumber -> PublicPoint
+calculatePublic curve d = q
+  where
+    g = ecc_g $ common_curve curve
+    q = pointMul curve d g
+
+-- | Generating a shared key using our private number and
+--   the other party public point.
+getShared :: Curve -> PrivateNumber -> PublicPoint -> SharedKey
+getShared curve db qa = SharedKey x
+  where
+    Point x _ = pointMul curve db qa
diff --git a/Crypto/PubKey/ECC/Prim.hs b/Crypto/PubKey/ECC/Prim.hs
--- a/Crypto/PubKey/ECC/Prim.hs
+++ b/Crypto/PubKey/ECC/Prim.hs
@@ -5,6 +5,8 @@
     ( pointAdd
     , pointDouble
     , pointMul
+    , isPointAtInfinity
+    , isPointValid
     ) where
 
 import Data.Maybe
@@ -12,6 +14,8 @@
 import Crypto.Number.F2m
 import Crypto.Types.PubKey.ECC
 
+--TODO: Extract helper function for `fromMaybe PointO...`
+
 -- | Elliptic Curve point addition.
 --
 -- /WARNING:/ Vulnerable to timing attacks.
@@ -22,10 +26,11 @@
 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
+    | otherwise = fromMaybe PointO $ do
+                      s <- divmod (yp - yq) (xp - xq) pr
+                      let xr = (s ^ (2::Int) - xp - xq) `mod` pr
+                          yr = (s * (xp - xr) - yp) `mod` pr
+                      return $ 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
@@ -39,30 +44,81 @@
 -- | 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 -> 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)
+pointDouble (CurveFP (CurvePrime pr cc)) (Point xp yp) = fromMaybe PointO $ do
+    lambda <- divmod (3 * xp ^ (2::Int) + a) (2 * yp) pr
+    let xr = (lambda ^ (2::Int) - 2 * xp) `mod` pr
+        yr = (lambda * (xp - xr) - yp) `mod` pr
     return $ Point xr yr
   where a = ecc_a cc
+pointDouble (CurveF2m (CurveBinary fx cc)) (Point xp yp)
+    | xp == 0   = PointO
+    | otherwise = 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
+pointMul _ _ PointO = PointO
+pointMul c n p@(Point xp yp)
+    | n <  0 = pointMul c (-n) (Point xp (-yp))
+    | n == 0 = PointO
     | n == 1 = p
     | odd n = pointAdd c p (pointMul c (n - 1) p)
     | otherwise = pointMul c (n `div` 2) (pointDouble c p)
 
+-- | Check if a point is the point at infinity.
+isPointAtInfinity :: Point -> Bool
+isPointAtInfinity PointO = True
+isPointAtInfinity _      = False
+
+-- | 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 -> Point -> Bool
+isPointValid _                           PointO      = True
+isPointValid (CurveFP (CurvePrime p cc)) (Point x y) =
+    isValid x && isValid y && (y ^ (2 :: Int)) `eqModP` (x ^ (3 :: Int) + a * x + b)
+  where a  = ecc_a cc
+        b  = ecc_b cc
+        eqModP z1 z2 = (z1 `mod` p) == (z2 `mod` p)
+        isValid e = e >= 0 && e < p
+isPointValid curve@(CurveF2m (CurveBinary fx cc)) pt@(Point x y) =
+    and [ isValid x
+        , isValid y
+        , ((((x `add` a) `mul` x `add` y) `mul` x) `add` b `add` (squareF2m fx y)) == 0
+        ]
+  where a  = ecc_a cc
+        b  = ecc_b cc
+        add = addF2m
+        mul = mulF2m fx
+        isValid e = modF2m fx e == e
+
 -- | div and mod
-divmod :: Integer -> Integer -> Integer -> Integer
-divmod y x m = y * fromJust (inverse (x `mod` m) m) `mod` m
+divmod :: Integer -> Integer -> Integer -> Maybe Integer
+divmod y x m = do
+    i <- inverse (x `mod` m) m
+    return $ y * i `mod` m
diff --git a/Tests/EccArithmetic.hs b/Tests/EccArithmetic.hs
new file mode 100644
--- /dev/null
+++ b/Tests/EccArithmetic.hs
@@ -0,0 +1,41 @@
+module EccArithmetic (properties_ecc_arithmetic) where
+
+import Test.Tasty.QuickCheck
+
+import Crypto.Types.PubKey.ECC
+import Crypto.PubKey.ECC.Generate
+import Crypto.PubKey.ECC.Prim
+
+data GeneratePoint1 = GeneratePoint1 Curve Point
+    deriving (Show,Eq)
+data GeneratePoint2 = GeneratePoint2 Curve Point Point
+    deriving (Show,Eq)
+
+arbitraryPoint curve = do
+    sec <- choose (1,n)
+    return $ pointMul curve sec g
+  where common = common_curve curve
+        n      = ecc_n common
+        g      = ecc_g common
+
+instance Arbitrary Curve where
+    arbitrary = elements $ map getCurveByName $ enumFrom SEC_p112r1
+
+instance Arbitrary GeneratePoint1 where
+    arbitrary = do
+        curve <- arbitrary
+        p1    <- arbitraryPoint curve
+        return $ GeneratePoint1 curve p1
+
+instance Arbitrary GeneratePoint2 where
+    arbitrary = do
+        curve <- arbitrary
+        p1    <- arbitraryPoint curve
+        p2    <- arbitraryPoint curve
+        return $ GeneratePoint2 curve p1 p2
+
+properties_ecc_arithmetic =
+    [ testProperty "commutative" $ \(GeneratePoint2 curve p1 p2) ->
+        pointAdd curve p1 p2 == pointAdd curve p2 p1
+    , testProperty "add-neutral" $ \(GeneratePoint1 curve p1) -> pointAdd curve p1 PointO == p1
+    ]
diff --git a/Tests/KAT.hs b/Tests/KAT.hs
--- a/Tests/KAT.hs
+++ b/Tests/KAT.hs
@@ -1,11 +1,9 @@
 {-# LANGUAGE OverloadedStrings #-}
 module KAT where
 
-import Test.Framework (Test, defaultMain, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
-import Test.QuickCheck
-import Test.QuickCheck.Test
-import Test.HUnit
+import Test.Tasty
+import Test.Tasty.HUnit
+import Test.Tasty.QuickCheck
 import System.IO (hFlush, stdout)
 
 import Data.ByteString (ByteString)
@@ -19,6 +17,7 @@
 import KAT.OAEP
 import KAT.PSS
 import KAT.DSA
+import KAT.ECC
 import KAT.ECDSA
 
 data VectorMgf = VectorMgf { seed :: ByteString
@@ -40,5 +39,8 @@
     , pssTests
     , oaepTests
     , dsaTests
+    , eccTests
     , ecdsaTests
     ]
+
+newKats = [ eccKatTests ]
diff --git a/Tests/KAT/DSA.hs b/Tests/KAT/DSA.hs
--- a/Tests/KAT/DSA.hs
+++ b/Tests/KAT/DSA.hs
@@ -8,9 +8,8 @@
 import qualified Crypto.PubKey.DSA as DSA
 import qualified Crypto.Hash.SHA1 as SHA1
 
-import Test.HUnit
-import Test.Framework (Test, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
+import Test.Tasty
+import Test.Tasty.HUnit
 
 data VectorDSA = VectorDSA
     { pgq :: DSA.Params
diff --git a/Tests/KAT/ECC.hs b/Tests/KAT/ECC.hs
new file mode 100644
--- /dev/null
+++ b/Tests/KAT/ECC.hs
@@ -0,0 +1,145 @@
+{-# LANGUAGE OverloadedStrings #-}
+module KAT.ECC (eccTests, eccKatTests) where
+
+import Control.Arrow (second)
+import Control.Applicative
+import Data.ByteString (ByteString)
+import Crypto.Number.Serialize
+
+import qualified Crypto.Types.PubKey.ECC as ECC
+import qualified Crypto.PubKey.ECC.Prim as ECC
+
+import Test.Tasty.KAT
+import Test.Tasty.KAT.FileLoader
+
+import Test.Tasty
+import Test.Tasty.HUnit
+
+
+data VectorPoint = VectorPoint
+    { curve :: ECC.Curve
+    , x     :: Integer
+    , y     :: Integer
+    , valid :: Bool
+    }
+
+vectorsPoint =
+    [ VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x     = 0x491c0c4761b0a4a147b5e4ce03a531546644f5d1e3d05e57
+        , y     = 0x6fa5addd47c5d6be3933fbff88f57a6c8ca0232c471965de
+        , valid = False -- point not on curve
+        }
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x646c22e8aa5f7833390e0399155ac198ae42470bba4fc834
+        , y    = 0x8d4afcfffd80e69a4d180178b37c44572495b7b267ee32a9
+        , valid = True
+        }
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x4c6b9ea0dec92ecfff7799470be6a2277b9169daf45d54bb
+        , y    = 0xf0eab42826704f51b26ae98036e83230becb639dd1964627
+        , valid = False -- point not on curve
+        }
+
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x0673c8bb717b055c3d6f55c06acfcfb7260361ed3ec0f414
+        , y    = 0xba8b172826eb0b854026968d2338a180450a27906f6eddea
+        , valid = True
+        }
+
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x82c949295156192df0b52480e38c810751ac570daec460a3
+        , y    = 0x200057ada615c80b8ff256ce8d47f2562b74a438f1921ac3
+        , valid = False -- point not on curve
+        }
+
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x284fbaa76ce0faae2ca4867d01092fa1ace5724cd12c8dd0
+        , y    = 0xe42af3dbf3206be3fcbcc3a7ccaf60c73dc29e7bb9b44fca
+        , valid = True
+        }
+
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x1b574acd4fb0f60dde3e3b5f3f0e94211f95112e43cba6fd2
+        , y    = 0xbcc1b8a770f01a22e84d7f14e44932ffe094d8e3b1e6ac26
+        , valid = False -- x or y out of range
+        }
+
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x16ba109f1f1bb44e0d05b80181c03412ea764a59601d17e9f
+        , y    = 0x0569a843dbb4e287db420d6b9fe30cd7b5d578b052315f56
+        , valid = False -- x or y out of range
+        }
+
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x1333308a7c833ede5189d25ea3525919c9bd16370d904938d
+        , y    = 0xb10fd01d67df75ff9b726c700c1b50596c9f0766ea56f80e
+        , valid = False -- x or y out of range
+        }
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x    = 0x9671ec444cff24c8a5be80b018fa505ed6109a731e88c91a
+        , y    = 0xfe79dae23008e46bf4230c895aab261a95845a77f06d0655
+        , valid = True
+        }
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x     = 0x158e8b6f0b14216bc52fe8897b4305d870ede70436a96741d
+        , y     = 0xfb3f970b19a313571a1a23be310923f85acc1cab0a157cbd
+        , valid = False -- x or y out of range
+        }
+    , VectorPoint
+        { curve = ECC.getCurveByName ECC.SEC_p192r1
+        , x     = 0xace95b650c08f73dbb4fa7b4bbdebd6b809a25b28ed135ef
+        , y     = 0xe9b8679404166d1329dd539ad52aad9a1b6681f5f26bb9aa
+        , valid = False -- point not on curve
+        }
+    ]
+
+doPointValidTest (i, vector) = testCase (show i) (valid vector @=? ECC.isPointValid (curve vector) (ECC.Point (x vector) (y vector)))
+
+eccTests = testGroup "ECC"
+    [ testGroup "valid-point" $ map doPointValidTest (zip [0..] vectorsPoint)
+    ]
+
+eccKatTests = do
+    res <- testKatLoad "KATs/ECC-PKV.txt" (map (second (map toVector)) . katLoaderSimple)
+    return $ testKatDetailed {-Grouped-} "ECC/valid-point" res (\g vect -> do
+        let c = ECC.getCurveByName <$> case g of
+                        "P-192" -> Just ECC.SEC_p192r1
+                        "P-224" -> Just ECC.SEC_p224r1
+                        "P-256" -> Just ECC.SEC_p256r1
+                        "P-384" -> Just ECC.SEC_p384r1
+                        "P-521" -> Just ECC.SEC_p521r1
+                        "B-163" -> Just ECC.SEC_t163r2
+                        "B-233" -> Just ECC.SEC_t233r1
+                        "B-283" -> Just ECC.SEC_t283r1
+                        "B-409" -> Just ECC.SEC_t409r1
+                        "B-571" -> Just ECC.SEC_t571r1
+                        ""      -> Nothing
+                        _       -> Nothing
+{-
+                        "K-163" -> Just ECC.SEC_t163k1
+                        "K-233" -> Just ECC.SEC_t233k1
+                        "K-283" -> Just ECC.SEC_t283k1
+                        "K-409" -> Just ECC.SEC_t409k1
+                        "K-571" -> Just ECC.SEC_t571k1
+-}
+        case c of
+            Nothing    -> return True
+            Just curve -> do
+                return (ECC.isPointValid curve (ECC.Point (x vect) (y vect)) == valid vect)
+        )
+
+  where toVector kvs =
+            case sequence $ map (flip lookup kvs) [ "Qx", "Qy", "Result" ] of
+                Just [qx,qy,res] -> VectorPoint undefined (valueHexInteger qx) (valueHexInteger qy) (head res /= 'F')
+                Nothing          -> error ("ERROR CRAP: " ++ show kvs) -- VectorPoint undefined 0 0 True
diff --git a/Tests/KAT/ECDSA.hs b/Tests/KAT/ECDSA.hs
--- a/Tests/KAT/ECDSA.hs
+++ b/Tests/KAT/ECDSA.hs
@@ -4,13 +4,14 @@
 
 import Data.ByteString (ByteString)
 
+import Crypto.Number.Serialize
+
 import qualified Crypto.PubKey.ECC.ECDSA as ECDSA
 import qualified Crypto.Types.PubKey.ECC as ECC
 import qualified Crypto.Hash.SHA1 as SHA1
 
-import Test.HUnit
-import Test.Framework (testGroup)
-import Test.Framework.Providers.HUnit (testCase)
+import Test.Tasty.HUnit
+import Test.Tasty
 
 data VectorECDSA = VectorECDSA
     { curve :: ECC.Curve
@@ -33,16 +34,44 @@
         , r     = 1176954224688105769566774212902092897866168635793
         , s     = 299742580584132926933316745664091704165278518100
         }
+    -- from official ECDSA KATs
     , VectorECDSA
         { curve = ECC.getCurveByName ECC.SEC_t163k1
-        , msg   = "abc"
-        , d     = 5321230001203043918714616464614664646674949479949
-        , q     = ECC.Point 0x037d529fa37e42195f10111127ffb2bb38644806bc
-                            0x0447026eee8b34157f3eb51be5185d2be0249ed776
-        , k     = 936523985789236956265265265235675811949404040044
-        , r     = 875196600601491789979810028167552198674202899628
-        , s     = 1935199835333115956886966454901154618180070051199
+        , msg   = i2osp 0xa2c1a03fdd00521bb08fc88d20344321977aaf637ef9d5470dd7d2c8628fc8d0d1f1d3587c6b3fd02386f8c13db341b14748a9475cc63baf065df64054b27d5c2cdf0f98e3bbb81d0b5dc94f8cdb87acf75720f6163de394c8c6af360bc1acb85b923a493b7b27cc111a257e36337bd94eb0fab9d5e633befb1ae7f1b244bfaa
+        , d     = 0x00000011f2626d90d26cb4c0379043b26e64107fc
+        , q     = ECC.Point 0x0389fa5ad7f8304325a8c060ef7dcb83042c045bc
+                            0x0eefa094a5054da196943cc80509dcb9f59e5bc2e
+        , k     = 0x0000000c3a4ff97286126dab1e5089395fcc47ebb
+        , r     = 0x0dbe6c3a1dc851e7f2338b5c26c62b4b37bf8035c
+        , s     = 0x1c76458135b1ff9fbd23009b8414a47996126b56a
         }
+    , VectorECDSA
+        { curve = ECC.getCurveByName ECC.SEC_t163k1
+        , msg   = i2osp 0x67048080daaeb77d3ac31babdf8be23dbe75ceb4dfb94aa8113db5c5dcb6fe14b70f717b7b0ed0881835a66a86e6d840ffcb7d976c75ef2d1d4322fbbc86357384e24707aef88cea2c41a01a9a3d1b9e72ce650c7fdecc4f9448d3a77df6cdf13647ab295bb3132de0b1b2c402d8d2de7d452f1e003e0695de1470d1064eee16
+        , d     = 0x00000006a3803301daee9af09bb5b6c991a4f49a4
+        , q     = ECC.Point 0x4b500f555e857da8c299780130c5c3f48f02ee322 0x5c1c0ae25b47f06cc46fb86b12d2d8c0ba6a4bf07
+        , k     = 0x0000002f39fbf77f3e0dc046116de692b6cf91b16
+        , r     = 0x3d3eeda42f65d727f4a564f1415654356c6c57a6c
+        , s     = 0x35e4d43c5f08baddf138449db1ad0b7872552b7cd
+        }
+    , VectorECDSA
+        { curve = ECC.getCurveByName ECC.SEC_t163k1
+        , msg   = i2osp 0x77e007dc2acd7248256165a4b30e98986f51a81efd926b85f74c81bc2a6d2bcd030060a844091e22fbb0ff3db5a20caaefb5d58ccdcbc27f0ff8a4d940e78f303079ec1ca5b0ca3d4ecc7580f8b34a9f0496c9e719d2ec3e1614b7644bc11179e895d2c0b58a1da204fbf0f6e509f97f983eacb6487092caf6e8e4e6b3c458b2
+        , d     = 0x0000002e28676514bd93fea11b62db0f6e324b18d
+        , q     = ECC.Point 0x3f9c90b71f6a1de20a2716f38ef1b5f98c757bd42 0x2ff0a5d266d447ef62d43fbca6c34c08c1ce35a40
+        , k     = 0x00000001233ae699883e74e7f4dfb5279ff22280a
+        , r     = 0x39de3cd2cf04145e522b8fba3f23e9218226e0860
+        , s     = 0x2af62bfb3cfa202e2342606ee5bb0934c3b0375b6
+        }
+    , VectorECDSA
+        { curve = ECC.getCurveByName ECC.SEC_t163k1
+        , msg   = i2osp 0xfbacfcce4688748406ddf5c3495021eef8fb399865b649eb2395a04a1ab28335da2c236d306fcc59f7b65ea931cf0139571e1538ede5688958c3ac69f47a285362f5ad201f89cc735b7b465408c2c41b310fc8908d0be45054df2a7351fae36b390e842f3b5cdd9ad832940df5b2d25c2ed43ce86eaf2508bcf401ae58bb1d47
+        , d     = 0x000000361dd088e3a6d3c910686c8dce57e5d4d8e
+        , q     = ECC.Point 0x064f905c1da9d7e9c32d81890ae6f30dcc7839d32 0x06f1faedb6d9032016d3b681e7cf69c29d29eb27b
+        , k     = 0x00000022f723e9f5da56d3d0837d5dca2f937395f
+        , r     = 0x374cdc8571083fecfbd4e25e1cd69ecc66b715f2d
+        , s     = 0x313b10949222929b2f20b15d446c27d6dcae3f086
+        }
     ]
 
 vectorToPrivate :: VectorECDSA -> ECDSA.PrivateKey
@@ -58,7 +87,7 @@
 doVerifyTest (i, vector) = testCase (show i) (True @=? actual)
   where actual = ECDSA.verify SHA1.hash (vectorToPublic vector) (ECDSA.Signature (r vector) (s vector)) (msg vector)
 
-ecdsaTests = testGroup "DSA"
+ecdsaTests = testGroup "ECDSA"
     [ testGroup "SHA1"
         [ testGroup "signature" $ map doSignatureTest (zip [0..] vectorsSHA1)
         , testGroup "verify" $ map doVerifyTest (zip [0..] vectorsSHA1)
diff --git a/Tests/KAT/OAEP.hs b/Tests/KAT/OAEP.hs
--- a/Tests/KAT/OAEP.hs
+++ b/Tests/KAT/OAEP.hs
@@ -10,9 +10,8 @@
 import qualified Crypto.PubKey.RSA.OAEP as OAEP
 import qualified Crypto.Hash.SHA1 as SHA1
 
-import Test.HUnit
-import Test.Framework (Test, defaultMain, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
+import Test.Tasty
+import Test.Tasty.HUnit
 
 rsaKeyInt = PrivateKey
     { private_pub = PublicKey
diff --git a/Tests/KAT/PSS.hs b/Tests/KAT/PSS.hs
--- a/Tests/KAT/PSS.hs
+++ b/Tests/KAT/PSS.hs
@@ -10,9 +10,8 @@
 import qualified Crypto.PubKey.RSA.PSS as PSS
 import qualified Crypto.Hash.SHA1 as SHA1
 
-import Test.HUnit
-import Test.Framework (Test, defaultMain, testGroup)
-import Test.Framework.Providers.HUnit (testCase)
+import Test.Tasty
+import Test.Tasty.HUnit
 
 data VectorPSS = VectorPSS { message :: ByteString
                            , salt :: ByteString
diff --git a/Tests/Tests.hs b/Tests/Tests.hs
--- a/Tests/Tests.hs
+++ b/Tests/Tests.hs
@@ -1,10 +1,8 @@
 {-# LANGUAGE OverloadedStrings #-}
 
-import Test.Framework (Test, defaultMain, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
+import Test.Tasty
+import Test.Tasty.QuickCheck
 
-import Test.QuickCheck
-import Test.QuickCheck.Test
 import System.IO (hFlush, stdout)
 
 import Control.Monad
@@ -33,6 +31,7 @@
 import RNG
 import KAT
 import PregenKeys
+import EccArithmetic
 
 withAleasInteger :: Rng -> Seed -> (Rng -> (a,Rng)) -> a
 withAleasInteger rng (Seed i) f = fst $ f $ reseed (i2osp (if i < 0 then -i else i)) rng
@@ -136,9 +135,6 @@
                    let q = generateQ curve d
                    return $ ECDSA.KeyPair curve q d
 
-instance Arbitrary Curve where
-    arbitrary = elements $ map getCurveByName $ enumFrom SEC_p112r1
-
 instance Arbitrary DH.PrivateNumber where
     arbitrary = fromIntegral <$> (suchThat (arbitrary :: Gen Integer) (\x -> x >= 1))
 
@@ -173,11 +169,15 @@
 
 asymOtherTests = testGroup "assymetric other tests"
     [ testProperty "DH valid" prop_dh_valid
+    , testGroup "ECC arithmetic" properties_ecc_arithmetic
     ]
 
-main = defaultMain
-    [ asymEncryptionTests
-    , asymSignatureTests
-    , asymOtherTests
-    , testGroup "KATs" katTests
-    ]
+main = do
+    kats <- sequence newKats
+    defaultMain $ testGroup "crypto-pubkey"
+        [ testGroup "KATs" katTests
+        , testGroup "KAT2s" kats
+        , asymEncryptionTests
+        , asymSignatureTests
+        , asymOtherTests
+        ]
diff --git a/crypto-pubkey.cabal b/crypto-pubkey.cabal
--- a/crypto-pubkey.cabal
+++ b/crypto-pubkey.cabal
@@ -1,5 +1,5 @@
 Name:                crypto-pubkey
-Version:             0.2.4
+Version:             0.2.8
 Description:
     Public Key cryptography
     .
@@ -14,16 +14,12 @@
 Synopsis:            Public Key cryptography
 Category:            Cryptography
 Build-Type:          Simple
-Homepage:            http://github.com/vincenthz/hs-crypto-pubkey
+Homepage:            https://github.com/vincenthz/hs-crypto-pubkey
 Cabal-Version:       >=1.8
 Extra-Source-Files:  Tests/*.hs
                      Tests/KAT/*.hs
                      Benchs/PregenKeys.hs
 
-Flag benchmark
-  Description:       Build benchmarks
-  Default:           False
-
 Library
   Build-Depends:     base >= 4 && < 5
                    , bytestring
@@ -43,6 +39,7 @@
                      Crypto.PubKey.MaskGenFunction
                      Crypto.PubKey.ECC.Generate
                      Crypto.PubKey.ECC.Prim
+                     Crypto.PubKey.ECC.DH
                      Crypto.PubKey.ECC.ECDSA
   other-modules:     Crypto.PubKey.ElGamal
                      Crypto.PubKey.RSA.Types
@@ -61,11 +58,10 @@
                    , crypto-pubkey-types
                    , crypto-numbers
                    , crypto-random
-                   , QuickCheck >= 2
-                   , HUnit
-                   , test-framework >= 0.3.3
-                   , test-framework-quickcheck2 >= 0.2.9
-                   , test-framework-hunit
+                   , tasty
+                   , tasty-quickcheck
+                   , tasty-hunit
+                   , tasty-kat
 
 Benchmark bench-crypto-pubkey
   hs-source-dirs:    Benchs
@@ -83,4 +79,4 @@
 
 source-repository head
   type:     git
-  location: git://github.com/vincenthz/hs-crypto-pubkey
+  location: https://github.com/vincenthz/hs-crypto-pubkey
