diff options
Diffstat (limited to 'cryptonite-backport/Crypto/PubKey/Curve25519.hs')
-rw-r--r-- | cryptonite-backport/Crypto/PubKey/Curve25519.hs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/cryptonite-backport/Crypto/PubKey/Curve25519.hs b/cryptonite-backport/Crypto/PubKey/Curve25519.hs new file mode 100644 index 00000000..42878691 --- /dev/null +++ b/cryptonite-backport/Crypto/PubKey/Curve25519.hs | |||
@@ -0,0 +1,131 @@ | |||
1 | -- | | ||
2 | -- Module : Crypto.PubKey.Curve25519 | ||
3 | -- License : BSD-style | ||
4 | -- Maintainer : Vincent Hanquez <vincent@snarc.org> | ||
5 | -- Stability : experimental | ||
6 | -- Portability : unknown | ||
7 | -- | ||
8 | -- Curve25519 support | ||
9 | -- | ||
10 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
11 | {-# LANGUAGE MagicHash #-} | ||
12 | {-# LANGUAGE ScopedTypeVariables #-} | ||
13 | module Crypto.PubKey.Curve25519 | ||
14 | ( SecretKey | ||
15 | , PublicKey | ||
16 | , DhSecret | ||
17 | -- * Smart constructors | ||
18 | , dhSecret | ||
19 | , publicKey | ||
20 | , secretKey | ||
21 | -- * methods | ||
22 | , dh | ||
23 | , toPublic | ||
24 | , generateSecretKey | ||
25 | ) where | ||
26 | |||
27 | import Data.Bits | ||
28 | import Data.Word | ||
29 | import Foreign.Ptr | ||
30 | import Foreign.Storable | ||
31 | import GHC.Ptr | ||
32 | |||
33 | -- import Crypto.Error | ||
34 | import Crypto.Error.Types | ||
35 | import Crypto.Internal.Compat | ||
36 | import Crypto.Internal.Imports | ||
37 | import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, ScrubbedBytes, Bytes, withByteArray) | ||
38 | import qualified Crypto.Internal.ByteArray as B | ||
39 | -- import Crypto.Error (CryptoFailable(..)) | ||
40 | import Crypto.Random | ||
41 | |||
42 | -- | A Curve25519 Secret key | ||
43 | newtype SecretKey = SecretKey ScrubbedBytes | ||
44 | deriving (Show,Eq,ByteArrayAccess,NFData) | ||
45 | |||
46 | -- | A Curve25519 public key | ||
47 | newtype PublicKey = PublicKey Bytes | ||
48 | deriving (Show,Eq,ByteArrayAccess,NFData) | ||
49 | |||
50 | -- | A Curve25519 Diffie Hellman secret related to a | ||
51 | -- public key and a secret key. | ||
52 | newtype DhSecret = DhSecret ScrubbedBytes | ||
53 | deriving (Show,Eq,ByteArrayAccess,NFData) | ||
54 | |||
55 | -- | Try to build a public key from a bytearray | ||
56 | publicKey :: ByteArrayAccess bs => bs -> CryptoFailable PublicKey | ||
57 | publicKey bs | ||
58 | | B.length bs == 32 = CryptoPassed $ PublicKey $ B.copyAndFreeze bs (\_ -> return ()) | ||
59 | | otherwise = CryptoFailed CryptoError_PublicKeySizeInvalid | ||
60 | |||
61 | -- | Try to build a secret key from a bytearray | ||
62 | secretKey :: ByteArrayAccess bs => bs -> CryptoFailable SecretKey | ||
63 | secretKey bs | ||
64 | | B.length bs == 32 = unsafeDoIO $ do | ||
65 | withByteArray bs $ \inp -> do | ||
66 | valid <- isValidPtr inp | ||
67 | if valid | ||
68 | then (CryptoPassed . SecretKey) <$> B.copy bs (\_ -> return ()) | ||
69 | else return $ CryptoFailed CryptoError_SecretKeyStructureInvalid | ||
70 | | otherwise = CryptoFailed CryptoError_SecretKeySizeInvalid | ||
71 | where | ||
72 | -- e[0] &= 0xf8; | ||
73 | -- e[31] &= 0x7f; | ||
74 | -- e[31] |= 40; | ||
75 | isValidPtr :: Ptr Word8 -> IO Bool | ||
76 | isValidPtr _ = do | ||
77 | --b0 <- peekElemOff inp 0 | ||
78 | --b31 <- peekElemOff inp 31 | ||
79 | return True | ||
80 | {- | ||
81 | return $ and [ testBit b0 0 == False | ||
82 | , testBit b0 1 == False | ||
83 | , testBit b0 2 == False | ||
84 | , testBit b31 7 == False | ||
85 | , testBit b31 6 == True | ||
86 | ] | ||
87 | -} | ||
88 | {-# NOINLINE secretKey #-} | ||
89 | |||
90 | -- | Create a DhSecret from a bytearray object | ||
91 | dhSecret :: ByteArrayAccess b => b -> CryptoFailable DhSecret | ||
92 | dhSecret bs | ||
93 | | B.length bs == 32 = CryptoPassed $ DhSecret $ B.copyAndFreeze bs (\_ -> return ()) | ||
94 | | otherwise = CryptoFailed CryptoError_SharedSecretSizeInvalid | ||
95 | |||
96 | -- | Compute the Diffie Hellman secret from a public key and a secret key | ||
97 | dh :: PublicKey -> SecretKey -> DhSecret | ||
98 | dh (PublicKey pub) (SecretKey sec) = DhSecret <$> | ||
99 | B.allocAndFreeze 32 $ \result -> | ||
100 | withByteArray sec $ \psec -> | ||
101 | withByteArray pub $ \ppub -> | ||
102 | ccryptonite_curve25519 result psec ppub | ||
103 | {-# NOINLINE dh #-} | ||
104 | |||
105 | -- | Create a public key from a secret key | ||
106 | toPublic :: SecretKey -> PublicKey | ||
107 | toPublic (SecretKey sec) = PublicKey <$> | ||
108 | B.allocAndFreeze 32 $ \result -> | ||
109 | withByteArray sec $ \psec -> | ||
110 | ccryptonite_curve25519 result psec basePoint | ||
111 | where | ||
112 | basePoint = Ptr "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# | ||
113 | {-# NOINLINE toPublic #-} | ||
114 | |||
115 | -- | Generate a secret key. | ||
116 | generateSecretKey :: MonadRandom m => m SecretKey | ||
117 | generateSecretKey = tweakToSecretKey <$> getRandomBytes 32 | ||
118 | where | ||
119 | tweakToSecretKey :: ScrubbedBytes -> SecretKey | ||
120 | tweakToSecretKey bin = SecretKey $ B.copyAndFreeze bin $ \inp -> do | ||
121 | modifyByte inp 0 (\e0 -> e0 .&. 0xf8) | ||
122 | modifyByte inp 31 (\e31 -> (e31 .&. 0x7f) .|. 0x40) | ||
123 | |||
124 | modifyByte :: Ptr Word8 -> Int -> (Word8 -> Word8) -> IO () | ||
125 | modifyByte p n f = peekByteOff p n >>= pokeByteOff p n . f | ||
126 | |||
127 | foreign import ccall "cryptonite_curve25519_donna" | ||
128 | ccryptonite_curve25519 :: Ptr Word8 -- ^ public | ||
129 | -> Ptr Word8 -- ^ secret | ||
130 | -> Ptr Word8 -- ^ basepoint | ||
131 | -> IO () | ||