diff options
Diffstat (limited to 'src/Network')
-rw-r--r-- | src/Network/DatagramServer.hs | 4 | ||||
-rw-r--r-- | src/Network/DatagramServer/Tox.hs | 70 |
2 files changed, 61 insertions, 13 deletions
diff --git a/src/Network/DatagramServer.hs b/src/Network/DatagramServer.hs index 8c4ec928..bcf8b9af 100644 --- a/src/Network/DatagramServer.hs +++ b/src/Network/DatagramServer.hs | |||
@@ -569,8 +569,10 @@ listener mgr@Manager{..} hs p = do | |||
569 | (bs, addr) <- liftIO $ do | 569 | (bs, addr) <- liftIO $ do |
570 | handle exceptions $ BS.recvFrom sock (optMaxMsgSize options) | 570 | handle exceptions $ BS.recvFrom sock (optMaxMsgSize options) |
571 | case parsePacket (msgProxy p) bs >>= \r -> (,) r <$> decodeHeaders ctx r of | 571 | case parsePacket (msgProxy p) bs >>= \r -> (,) r <$> decodeHeaders ctx r of |
572 | Left e -> -- XXX: Send parse failure message? | 572 | Left e -> do |
573 | -- XXX: Send parse failure message? | ||
573 | -- liftIO \$ sendMessage sock addr $ encodeHeaders ctx (unknownMessage e) | 574 | -- liftIO \$ sendMessage sock addr $ encodeHeaders ctx (unknownMessage e) |
575 | logMsg 'W' "listener" (T.pack $ show e) | ||
574 | return () -- Without transaction id, error message isn't very useful. | 576 | return () -- Without transaction id, error message isn't very useful. |
575 | Right (raw,m) -> | 577 | Right (raw,m) -> |
576 | case envelopeClass m of | 578 | case envelopeClass m of |
diff --git a/src/Network/DatagramServer/Tox.hs b/src/Network/DatagramServer/Tox.hs index 85ee269c..5003f3a4 100644 --- a/src/Network/DatagramServer/Tox.hs +++ b/src/Network/DatagramServer/Tox.hs | |||
@@ -34,7 +34,9 @@ import qualified Network.DatagramServer.Types as Envelope (NodeId) | |||
34 | import Crypto.PubKey.ECC.Types | 34 | import Crypto.PubKey.ECC.Types |
35 | import Crypto.PubKey.Curve25519 | 35 | import Crypto.PubKey.Curve25519 |
36 | import Crypto.ECC.Class | 36 | import Crypto.ECC.Class |
37 | import qualified Crypto.Cipher.XSalsa as Salsa20 | 37 | import qualified Crypto.Cipher.Salsa as Salsa |
38 | import qualified Crypto.Cipher.XSalsa as XSalsa | ||
39 | import qualified Crypto.MAC.Poly1305 as Poly1305 | ||
38 | import Data.LargeWord | 40 | import Data.LargeWord |
39 | import Foreign.Ptr | 41 | import Foreign.Ptr |
40 | import Foreign.Storable | 42 | import Foreign.Storable |
@@ -42,10 +44,13 @@ import Foreign.Marshal.Alloc | |||
42 | import Data.Typeable | 44 | import Data.Typeable |
43 | import StaticAssert | 45 | import StaticAssert |
44 | import Crypto.Error.Types | 46 | import Crypto.Error.Types |
47 | import qualified Crypto.Error as Cryptonite | ||
45 | import Data.Hashable | 48 | import Data.Hashable |
46 | import Text.PrettyPrint as PP hiding ((<>)) | 49 | import Text.PrettyPrint as PP hiding ((<>)) |
47 | import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) | 50 | import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) |
48 | import Data.ByteArray (convert) | 51 | import qualified Data.ByteArray as BA |
52 | import Data.ByteArray ( Bytes, convert ) | ||
53 | import Data.Monoid | ||
49 | 54 | ||
50 | 55 | ||
51 | type Key32 = Word256 -- 32 byte key | 56 | type Key32 = Word256 -- 32 byte key |
@@ -224,26 +229,29 @@ data ToxCipherContext = ToxCipherContext | |||
224 | { dhtSecretKey :: SecretKey | 229 | { dhtSecretKey :: SecretKey |
225 | } | 230 | } |
226 | 231 | ||
227 | newtype Ciphered = Ciphered { cipheredBytes :: ByteString } | 232 | data Ciphered = Ciphered { cipheredMAC :: Poly1305.Auth |
233 | , cipheredBytes :: ByteString } | ||
228 | 234 | ||
229 | getMessage :: Get (Message Ciphered) | 235 | getMessage :: Get (Message Ciphered) |
230 | getMessage = do | 236 | getMessage = do |
231 | typ <- get | 237 | typ <- get |
232 | nid <- get | 238 | nid <- get |
233 | tid <- get | 239 | tid <- get |
240 | mac <- Poly1305.Auth . convert <$> getBytes 2 | ||
234 | cnt <- remaining | 241 | cnt <- remaining |
235 | bs <- getBytes cnt | 242 | bs <- getBytes cnt |
236 | return Message { msgType = typ | 243 | return Message { msgType = typ |
237 | , msgClient = nid | 244 | , msgClient = nid |
238 | , msgNonce = tid | 245 | , msgNonce = tid |
239 | , msgPayload = Ciphered bs } | 246 | , msgPayload = Ciphered mac bs } |
240 | 247 | ||
241 | putMessage :: Message Ciphered -> Put | 248 | putMessage :: Message Ciphered -> Put |
242 | putMessage (Message {..}) = do | 249 | putMessage (Message {..}) = do |
243 | put msgType | 250 | put msgType |
244 | put msgClient | 251 | put msgClient |
245 | put msgNonce | 252 | put msgNonce |
246 | let Ciphered bs = msgPayload | 253 | let Ciphered (Poly1305.Auth mac) bs = msgPayload |
254 | putByteString (convert mac) | ||
247 | putByteString bs | 255 | putByteString bs |
248 | 256 | ||
249 | id2key :: NodeId Message -> PublicKey | 257 | id2key :: NodeId Message -> PublicKey |
@@ -251,20 +259,58 @@ id2key recipient = case publicKey recipient of | |||
251 | CryptoPassed key -> key | 259 | CryptoPassed key -> key |
252 | CryptoFailed e -> error ("id2key: "++show e) | 260 | CryptoFailed e -> error ("id2key: "++show e) |
253 | 261 | ||
254 | lookupSecret :: ToxCipherContext -> NodeId Message -> TransactionID Message -> Salsa20.State | 262 | |
255 | lookupSecret ctx recipient nonce = Salsa20.initialize 20 key nonce | 263 | zeros32 :: Bytes |
264 | zeros32 = BA.replicate 32 0 | ||
265 | |||
266 | zeros24 :: Bytes | ||
267 | zeros24 = BA.take 24 zeros32 | ||
268 | |||
269 | hsalsa20 k n = a <> b | ||
256 | where | 270 | where |
257 | key = ecdh (Proxy :: Proxy Curve_X25519) (dhtSecretKey ctx) (id2key recipient) -- ByteArrayAccess b => b | 271 | Salsa.State st = XSalsa.initialize 20 k n |
272 | (_, as) = BA.splitAt 4 st | ||
273 | (a, xs) = BA.splitAt 16 as | ||
274 | (_, bs) = BA.splitAt 24 xs | ||
275 | (b, _ ) = BA.splitAt 16 bs | ||
276 | |||
277 | lookupSecret :: ToxCipherContext -> NodeId Message -> TransactionID Message -> (Poly1305.State, XSalsa.State) | ||
278 | lookupSecret ctx recipient nonce = (hash, crypt) | ||
279 | where | ||
280 | -- diffie helman | ||
281 | shared = ecdh (Proxy :: Proxy Curve_X25519) (dhtSecretKey ctx) (id2key recipient) -- ByteArrayAccess b => b | ||
282 | -- shared secret XSalsa key | ||
283 | k = hsalsa20 shared zeros24 | ||
284 | -- cipher state | ||
285 | st0 = XSalsa.initialize 20 k nonce | ||
286 | -- Poly1305 key | ||
287 | (rs, crypt) = XSalsa.combine st0 zeros32 | ||
288 | Cryptonite.CryptoPassed hash = Poly1305.initialize rs -- TODO: Pattern fail? | ||
258 | 289 | ||
259 | decipher :: ToxCipherContext -> Message Ciphered -> Either String (Message ByteString) | 290 | decipher :: ToxCipherContext -> Message Ciphered -> Either String (Message ByteString) |
260 | decipher ctx ciphered = Right (fst . Salsa20.combine st . cipheredBytes <$> ciphered) | 291 | decipher ctx ciphered = mapM (decipherAndAuth hash crypt) ciphered |
261 | where | 292 | where |
262 | st = lookupSecret ctx (msgClient ciphered) (msgNonce ciphered) | 293 | (hash, crypt) = lookupSecret ctx (msgClient ciphered) (msgNonce ciphered) |
263 | 294 | ||
264 | encipher :: ToxCipherContext -> NodeId Message -> Message ByteString -> Message Ciphered | 295 | encipher :: ToxCipherContext -> NodeId Message -> Message ByteString -> Message Ciphered |
265 | encipher ctx recipient plain = Ciphered . fst . Salsa20.combine st <$> plain | 296 | encipher ctx recipient plain = encipherAndHash hash crypt <$> plain |
266 | where | 297 | where |
267 | st = lookupSecret ctx recipient (msgNonce plain) | 298 | (hash, crypt) = lookupSecret ctx recipient (msgNonce plain) |
299 | |||
300 | encipherAndHash :: Poly1305.State -> XSalsa.State -> ByteString -> Ciphered | ||
301 | encipherAndHash hash crypt m = Ciphered a c | ||
302 | where | ||
303 | c = fst . XSalsa.combine crypt $ m | ||
304 | a = Poly1305.finalize . Poly1305.update hash $ c | ||
305 | |||
306 | decipherAndAuth :: Poly1305.State -> XSalsa.State -> Ciphered -> Either String ByteString | ||
307 | decipherAndAuth hash crypt (Ciphered mac c) | ||
308 | | (a == mac) = Right m | ||
309 | | otherwise = Left "decipherAndAuth: auth fail" | ||
310 | where | ||
311 | m = fst . XSalsa.combine crypt $ c | ||
312 | a = Poly1305.finalize . Poly1305.update hash $ c | ||
313 | |||
268 | 314 | ||
269 | -- see rfc7748 | 315 | -- see rfc7748 |
270 | -- | 316 | -- |