diff options
author | joe <joe@jerkface.net> | 2017-07-10 20:30:10 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-07-10 20:30:10 -0400 |
commit | 2fdb0342f8cfcaf4924a0ce43e7fccb236eb0d5e (patch) | |
tree | fe013b9d665d6a6c03f6a35af017851f105115c0 /src/Network/DatagramServer | |
parent | c565ec07f37006a5abb7b3bc5a1b08013fbeb5d7 (diff) |
Fixed Tox decryption.
Diffstat (limited to 'src/Network/DatagramServer')
-rw-r--r-- | src/Network/DatagramServer/Tox.hs | 125 |
1 files changed, 112 insertions, 13 deletions
diff --git a/src/Network/DatagramServer/Tox.hs b/src/Network/DatagramServer/Tox.hs index 5003f3a4..9d60d066 100644 --- a/src/Network/DatagramServer/Tox.hs +++ b/src/Network/DatagramServer/Tox.hs | |||
@@ -51,6 +51,10 @@ import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) | |||
51 | import qualified Data.ByteArray as BA | 51 | import qualified Data.ByteArray as BA |
52 | import Data.ByteArray ( Bytes, convert ) | 52 | import Data.ByteArray ( Bytes, convert ) |
53 | import Data.Monoid | 53 | import Data.Monoid |
54 | import System.Endian | ||
55 | import qualified Data.ByteString.Base16 as Base16 | ||
56 | import qualified Data.ByteString.Char8 as C8 | ||
57 | import qualified Data.ByteString.Char8 as C8 | ||
54 | 58 | ||
55 | 59 | ||
56 | type Key32 = Word256 -- 32 byte key | 60 | type Key32 = Word256 -- 32 byte key |
@@ -119,9 +123,14 @@ data Message a = Message | |||
119 | , msgNonce :: TransactionID Message | 123 | , msgNonce :: TransactionID Message |
120 | , msgPayload :: a | 124 | , msgPayload :: a |
121 | } | 125 | } |
122 | deriving (Show, Generic, Functor, Foldable, Traversable) | 126 | deriving (Eq, Show, Generic, Functor, Foldable, Traversable) |
123 | 127 | ||
124 | deriving instance Show (NodeId Message) -- TODO: print as hex | 128 | instance Show (NodeId Message) where |
129 | showsPrec d pubkey s = | ||
130 | "NodeId \"" ++ C8.unpack (Base16.encode $ convert pubkey) ++ '"':s | ||
131 | |||
132 | instance Show (TransactionID Message) where | ||
133 | showsPrec d nonce = mappend "TID " . quoted (mappend $ bin2hex nonce) | ||
125 | 134 | ||
126 | isQuery :: Message a -> Bool | 135 | isQuery :: Message a -> Bool |
127 | isQuery (Message { msgType = SendNodes }) = False | 136 | isQuery (Message { msgType = SendNodes }) = False |
@@ -231,13 +240,26 @@ data ToxCipherContext = ToxCipherContext | |||
231 | 240 | ||
232 | data Ciphered = Ciphered { cipheredMAC :: Poly1305.Auth | 241 | data Ciphered = Ciphered { cipheredMAC :: Poly1305.Auth |
233 | , cipheredBytes :: ByteString } | 242 | , cipheredBytes :: ByteString } |
243 | deriving Eq | ||
244 | |||
245 | quoted shows s = '"':shows ('"':s) | ||
246 | |||
247 | bin2hex :: ByteArrayAccess bs => bs -> String | ||
248 | bin2hex = C8.unpack . Base16.encode . convert | ||
249 | |||
250 | instance Show Ciphered where | ||
251 | showsPrec d (Ciphered (Poly1305.Auth mac) bytes) = | ||
252 | mappend "Ciphered (Auth " | ||
253 | . quoted (mappend $ bin2hex mac) | ||
254 | . (") " ++) | ||
255 | . quoted (mappend $ bin2hex bytes) | ||
234 | 256 | ||
235 | getMessage :: Get (Message Ciphered) | 257 | getMessage :: Get (Message Ciphered) |
236 | getMessage = do | 258 | getMessage = do |
237 | typ <- get | 259 | typ <- get |
238 | nid <- get | 260 | nid <- get |
239 | tid <- get | 261 | tid <- get |
240 | mac <- Poly1305.Auth . convert <$> getBytes 2 | 262 | mac <- Poly1305.Auth . convert <$> getBytes 16 |
241 | cnt <- remaining | 263 | cnt <- remaining |
242 | bs <- getBytes cnt | 264 | bs <- getBytes cnt |
243 | return Message { msgType = typ | 265 | return Message { msgType = typ |
@@ -254,11 +276,19 @@ putMessage (Message {..}) = do | |||
254 | putByteString (convert mac) | 276 | putByteString (convert mac) |
255 | putByteString bs | 277 | putByteString bs |
256 | 278 | ||
279 | -- XXX: assumes ByteArray is little-endian | ||
257 | id2key :: NodeId Message -> PublicKey | 280 | id2key :: NodeId Message -> PublicKey |
258 | id2key recipient = case publicKey recipient of | 281 | id2key recipient = case publicKey recipient of |
259 | CryptoPassed key -> key | 282 | CryptoPassed key -> key |
260 | CryptoFailed e -> error ("id2key: "++show e) | 283 | CryptoFailed e -> error ("id2key: "++show e) |
261 | 284 | ||
285 | -- XXX: S.decode is Big-endian | ||
286 | -- TODO: implement ByteArray instance, avoid S.decode | ||
287 | key2id :: PublicKey -> NodeId Message | ||
288 | key2id pk = case S.decode (BA.convert pk) of | ||
289 | Left _ -> error "key2id" | ||
290 | Right nid -> nid | ||
291 | |||
262 | 292 | ||
263 | zeros32 :: Bytes | 293 | zeros32 :: Bytes |
264 | zeros32 = BA.replicate 32 0 | 294 | zeros32 = BA.replicate 32 0 |
@@ -305,6 +335,11 @@ encipherAndHash hash crypt m = Ciphered a c | |||
305 | 335 | ||
306 | decipherAndAuth :: Poly1305.State -> XSalsa.State -> Ciphered -> Either String ByteString | 336 | decipherAndAuth :: Poly1305.State -> XSalsa.State -> Ciphered -> Either String ByteString |
307 | decipherAndAuth hash crypt (Ciphered mac c) | 337 | decipherAndAuth hash crypt (Ciphered mac c) |
338 | {- | ||
339 | | C8.length m /= C8.length c = Left $ "Unequal lengths: "++show (C8.length m, C8.length c) | ||
340 | -- | C8.length c /= 40 = Left $ "Unexpected c length: " ++ show (C8.length c, bin2hex c) | ||
341 | | otherwise = Right m | ||
342 | -} | ||
308 | | (a == mac) = Right m | 343 | | (a == mac) = Right m |
309 | | otherwise = Left "decipherAndAuth: auth fail" | 344 | | otherwise = Left "decipherAndAuth: auth fail" |
310 | where | 345 | where |
@@ -340,14 +375,16 @@ curve25519 = CurveFP (CurvePrime prime curvecommon) | |||
340 | 375 | ||
341 | instance Envelope Message where | 376 | instance Envelope Message where |
342 | newtype TransactionID Message = TID Nonce24 | 377 | newtype TransactionID Message = TID Nonce24 |
343 | deriving (Eq,Ord,Show,Serialize) -- Read | 378 | deriving (Eq,Ord) -- Read |
344 | 379 | ||
345 | newtype NodeId Message = NodeId Word256 | 380 | newtype NodeId Message = NodeId Word256 |
346 | deriving (Serialize, Eq, Ord, Bits, FiniteBits) | 381 | deriving (Eq, Ord, Bits, FiniteBits) |
347 | 382 | ||
348 | type QueryMethod Message = MessageType | 383 | type QueryMethod Message = MessageType |
349 | 384 | ||
350 | newtype QueryExtra Message = QueryNonce { qryNonce :: Nonce8 } | 385 | newtype QueryExtra Message = QueryNonce { qryNonce :: Nonce8 } |
386 | deriving (Eq, Ord, Show) | ||
387 | |||
351 | newtype ResponseExtra Message = ResponseNonce { rspNonce :: Nonce8 } | 388 | newtype ResponseExtra Message = ResponseNonce { rspNonce :: Nonce8 } |
352 | 389 | ||
353 | data PacketDestination Message = ToxAddr { toxID :: NodeId Message | 390 | data PacketDestination Message = ToxAddr { toxID :: NodeId Message |
@@ -381,23 +418,83 @@ instance Envelope Message where | |||
381 | $ S.decode $ Char8.pack (take 24 $ show cnt ++ repeat ' ') | 418 | $ S.decode $ Char8.pack (take 24 $ show cnt ++ repeat ' ') |
382 | 419 | ||
383 | 420 | ||
421 | {- | ||
422 | instance Serialize (TransactionID Message) where | ||
423 | get = do | ||
424 | lo <- getWord64le | ||
425 | mid <- getWord64le | ||
426 | hi <- getWord64le | ||
427 | return $ TID (LargeKey lo | ||
428 | (LargeKey mid hi)) | ||
429 | |||
430 | put (TID (LargeKey lo (LargeKey mid hi))) = do | ||
431 | putWord64le lo | ||
432 | putWord64le mid | ||
433 | putWord64le hi | ||
434 | |||
435 | instance Serialize (NodeId Message) where | ||
436 | get = do | ||
437 | lo <- getWord64le | ||
438 | mid <- getWord64le | ||
439 | hi <- getWord64le | ||
440 | highest <- getWord64le | ||
441 | return $ NodeId (LargeKey lo | ||
442 | (LargeKey mid | ||
443 | (LargeKey hi highest))) | ||
444 | put (NodeId (LargeKey lo (LargeKey mid (LargeKey hi highest)))) = do | ||
445 | putWord64le lo | ||
446 | putWord64le mid | ||
447 | putWord64le hi | ||
448 | putWord64le highest | ||
449 | |||
450 | -} | ||
451 | |||
452 | instance Serialize (TransactionID Message) where | ||
453 | get = do | ||
454 | hi <- getWord64be | ||
455 | mid <- getWord64be | ||
456 | lo <- getWord64be | ||
457 | return $ TID (LargeKey lo | ||
458 | (LargeKey mid hi)) | ||
459 | |||
460 | put (TID (LargeKey lo (LargeKey mid hi))) = do | ||
461 | putWord64be hi | ||
462 | putWord64be mid | ||
463 | putWord64be lo | ||
464 | |||
465 | instance Serialize (NodeId Message) where | ||
466 | get = do | ||
467 | highest <- getWord64be | ||
468 | hi <- getWord64be | ||
469 | mid <- getWord64be | ||
470 | lo <- getWord64be | ||
471 | return $ NodeId (LargeKey lo | ||
472 | (LargeKey mid | ||
473 | (LargeKey hi highest))) | ||
474 | put (NodeId (LargeKey lo (LargeKey mid (LargeKey hi highest)))) = do | ||
475 | putWord64be highest | ||
476 | putWord64be hi | ||
477 | putWord64be mid | ||
478 | putWord64be lo | ||
479 | |||
480 | |||
384 | staticAssert isLittleEndian -- assumed by 'withWord64Ptr' | 481 | staticAssert isLittleEndian -- assumed by 'withWord64Ptr' |
385 | 482 | ||
386 | with3Word64Ptr :: Nonce24 -> (Ptr Word64 -> IO a) -> IO a | 483 | with3Word64Ptr :: Nonce24 -> (Ptr Word64 -> IO a) -> IO a |
387 | with3Word64Ptr (LargeKey wlo (LargeKey wmid whi)) kont = | 484 | with3Word64Ptr (LargeKey wlo (LargeKey wmid whi)) kont = |
388 | allocaBytes (sizeOf wlo * 3) $ \p -> do | 485 | allocaBytes (sizeOf wlo * 3) $ \p -> do |
389 | pokeElemOff p 0 wlo | 486 | pokeElemOff p 2 $ toBE64 wlo |
390 | pokeElemOff p 1 wmid | 487 | pokeElemOff p 1 $ toBE64 wmid |
391 | pokeElemOff p 2 whi | 488 | pokeElemOff p 0 $ toBE64 whi |
392 | kont p | 489 | kont p |
393 | 490 | ||
394 | with4Word64Ptr :: Key32 -> (Ptr Word64 -> IO a) -> IO a | 491 | with4Word64Ptr :: Key32 -> (Ptr Word64 -> IO a) -> IO a |
395 | with4Word64Ptr (LargeKey wlo (LargeKey wmid (LargeKey whi whighest))) kont = | 492 | with4Word64Ptr (LargeKey wlo (LargeKey wmid (LargeKey whi whighest))) kont = |
396 | allocaBytes (sizeOf wlo * 4) $ \p -> do | 493 | allocaBytes (sizeOf wlo * 4) $ \p -> do |
397 | pokeElemOff p 0 wlo | 494 | pokeElemOff p 3 $ toBE64 wlo |
398 | pokeElemOff p 1 wmid | 495 | pokeElemOff p 2 $ toBE64 wmid |
399 | pokeElemOff p 2 whi | 496 | pokeElemOff p 1 $ toBE64 whi |
400 | pokeElemOff p 3 whighest | 497 | pokeElemOff p 0 $ toBE64 whighest |
401 | kont p | 498 | kont p |
402 | 499 | ||
403 | 500 | ||
@@ -440,13 +537,15 @@ instance WireFormat ByteString Message where | |||
440 | 537 | ||
441 | initializeServerState _ _ = do | 538 | initializeServerState _ _ = do |
442 | k <- generateSecretKey | 539 | k <- generateSecretKey |
540 | {- | ||
443 | nid <- withByteArray (toPublic k) $ \p -> do | 541 | nid <- withByteArray (toPublic k) $ \p -> do |
444 | wlo <- peekElemOff p 0 | 542 | wlo <- peekElemOff p 0 |
445 | wmid <- peekElemOff p 1 | 543 | wmid <- peekElemOff p 1 |
446 | whi <- peekElemOff p 2 | 544 | whi <- peekElemOff p 2 |
447 | whigest <- peekElemOff p 3 | 545 | whigest <- peekElemOff p 3 |
448 | return $ LargeKey wlo (LargeKey wmid (LargeKey whi whigest)) | 546 | return $ LargeKey wlo (LargeKey wmid (LargeKey whi whigest)) |
449 | return (NodeId nid, ToxCipherContext k) | 547 | -} |
548 | return (key2id $ toPublic k, ToxCipherContext k) | ||
450 | 549 | ||
451 | 550 | ||
452 | instance Read (NodeId Message) where readsPrec d s = map (\(w,xs) -> (NodeId w, xs)) $ decodeHex s | 551 | instance Read (NodeId Message) where readsPrec d s = map (\(w,xs) -> (NodeId w, xs)) $ decodeHex s |