summaryrefslogtreecommitdiff
path: root/src/Network/Tox/Onion/Transport.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-11-05 01:25:36 -0500
committerjoe <joe@jerkface.net>2017-11-05 01:25:36 -0500
commit8039d812b7ea8ae566f8873452ac34597336ddfc (patch)
tree2b28e0b1ea90a4eb1122c723b82e580873a33cde /src/Network/Tox/Onion/Transport.hs
parentcb7337dc453131864f2692ef202230f2e7ae740b (diff)
Adapted computeSharedSecret to a side-effecting interface.
This is to ready the tree for a memoizing cache of shared secrets.
Diffstat (limited to 'src/Network/Tox/Onion/Transport.hs')
-rw-r--r--src/Network/Tox/Onion/Transport.hs178
1 files changed, 102 insertions, 76 deletions
diff --git a/src/Network/Tox/Onion/Transport.hs b/src/Network/Tox/Onion/Transport.hs
index 5b7aad0b..539e7cee 100644
--- a/src/Network/Tox/Onion/Transport.hs
+++ b/src/Network/Tox/Onion/Transport.hs
@@ -231,19 +231,21 @@ routeId :: NodeId -> RouteId
231routeId nid = RouteId $ mod (hash nid) 12 231routeId nid = RouteId $ mod (hash nid) 12
232 232
233 233
234encodeOnionAddr :: (NodeInfo -> RouteId -> IO (Maybe OnionRoute)) 234encodeOnionAddr :: TransportCrypto
235 -> (NodeInfo -> RouteId -> IO (Maybe OnionRoute))
235 -> (OnionMessage Encrypted,OnionDestination RouteId) 236 -> (OnionMessage Encrypted,OnionDestination RouteId)
236 -> IO (Maybe (ByteString, SockAddr)) 237 -> IO (Maybe (ByteString, SockAddr))
237encodeOnionAddr _ (msg,OnionToOwner ni p) = 238encodeOnionAddr crypto _ (msg,OnionToOwner ni p) =
238 return $ Just ( runPut $ putResponse (OnionResponse p msg) 239 return $ Just ( runPut $ putResponse (OnionResponse p msg)
239 , nodeAddr ni ) 240 , nodeAddr ni )
240encodeOnionAddr getRoute (msg,OnionDestination x ni Nothing) = do 241encodeOnionAddr crypto getRoute (msg,OnionDestination x ni Nothing) = do
241 encodeOnionAddr getRoute (msg,OnionDestination x ni (Just $ routeId $ nodeId ni) ) 242 encodeOnionAddr crypto getRoute (msg,OnionDestination x ni (Just $ routeId $ nodeId ni) )
242 -- hPutStrLn stderr $ "ONION encode missing routeid" 243 -- hPutStrLn stderr $ "ONION encode missing routeid"
243 -- return Nothing 244 -- return Nothing
244encodeOnionAddr getRoute (msg,OnionDestination _ ni (Just rid)) = do 245encodeOnionAddr crypto getRoute (msg,OnionDestination _ ni (Just rid)) = do
245 let go route = do 246 let go route = do
246 return ( runPut $ putRequest $ wrapForRoute msg ni route 247 req <- wrapForRoute crypto msg ni route
248 return ( runPut $ putRequest req
247 , nodeAddr $ routeNodeA route) 249 , nodeAddr $ routeNodeA route)
248 mapM' f x = do 250 mapM' f x = do
249 let _ = x :: Maybe OnionRoute 251 let _ = x :: Maybe OnionRoute
@@ -482,7 +484,8 @@ handleOnionRequest proxy crypto saddr udp kont (OnionRequest nonce msg rpath) =
482 hPutStrLn stderr $ "handleOnionRequest " ++ show n 484 hPutStrLn stderr $ "handleOnionRequest " ++ show n
483 (sym, snonce) <- atomically ( (,) <$> transportSymmetric crypto 485 (sym, snonce) <- atomically ( (,) <$> transportSymmetric crypto
484 <*> transportNewNonce crypto ) 486 <*> transportNewNonce crypto )
485 case peelOnion crypto nonce msg of 487 peeled <- peelOnion crypto nonce msg
488 case peeled of
486 Left e -> do 489 Left e -> do
487 -- todo report encryption error 490 -- todo report encryption error
488 hPutStrLn stderr $ unwords [ "peelOnion:", show n, either show show (either4or6 saddr), e] 491 hPutStrLn stderr $ unwords [ "peelOnion:", show n, either show show (either4or6 saddr), e]
@@ -505,9 +508,9 @@ peelOnion :: Serialize (Addressed (Forwarding n t))
505 => TransportCrypto 508 => TransportCrypto
506 -> Nonce24 509 -> Nonce24
507 -> Forwarding (S n) t 510 -> Forwarding (S n) t
508 -> Either String (Addressed (Forwarding n t)) 511 -> IO (Either String (Addressed (Forwarding n t)))
509peelOnion crypto nonce (Forwarding k fwd) = 512peelOnion crypto nonce (Forwarding k fwd) = do
510 fmap runIdentity $ uncomposed $ decryptMessage (dhtKey crypto) nonce (Right $ Asymm k nonce fwd) 513 fmap runIdentity . uncomposed <$> decryptMessage crypto (dhtKey crypto) nonce (Right $ Asymm k nonce fwd)
511 514
512handleOnionResponse :: (KnownPeanoNat n, Sized (ReturnPath n), Serialize (ReturnPath n)) => proxy (S n) -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionResponse (S n) -> IO a 515handleOnionResponse :: (KnownPeanoNat n, Sized (ReturnPath n), Serialize (ReturnPath n)) => proxy (S n) -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionResponse (S n) -> IO a
513handleOnionResponse proxy crypto saddr udp kont (OnionResponse path msg) = do 516handleOnionResponse proxy crypto saddr udp kont (OnionResponse path msg) = do
@@ -662,27 +665,42 @@ selectKey crypto _ rpath@(OnionDestination (AnnouncingAlias skey pkey) _ _)
662 = return (skey, pkey) 665 = return (skey, pkey)
663selectKey crypto msg rpath = return $ aliasKey crypto rpath 666selectKey crypto msg rpath = return $ aliasKey crypto rpath
664 667
665encrypt :: TransportCrypto -> OnionMessage Identity -> OnionDestination r -> IO (OnionMessage Encrypted, OnionDestination r) 668encrypt :: TransportCrypto
669 -> OnionMessage Identity
670 -> OnionDestination r
671 -> IO (OnionMessage Encrypted, OnionDestination r)
666encrypt crypto msg rpath = do 672encrypt crypto msg rpath = do
667 (skey,pkey) <- selectKey crypto msg rpath -- source key 673 (skey,pkey) <- selectKey crypto msg rpath -- source key
668 let okey = onionKey rpath -- destination key 674 let okey = onionKey rpath -- destination key
669 return ( transcode ( (. (runIdentity . either id asymmData)) 675 encipher1 :: Serialize a => SecretKey -> PublicKey -> Nonce24 -> a -> (IO ∘ Encrypted) a
670 . encryptMessage skey okey) 676 encipher1 sk pk n a = Composed $ do
671 msg 677 secret <- lookupSharedSecret crypto sk pk n
672 , rpath) 678 return $ ToxCrypto.encrypt secret $ encodePlain a
673 679 encipher :: Serialize a => Nonce24 -> Either (Identity a) (Asymm (Identity a)) -> (IO ∘ Encrypted) a
674encryptMessage :: Serialize a => 680 encipher n d = encipher1 skey okey n $ either runIdentity (runIdentity . asymmData) d
675 SecretKey -> PublicKey -> Nonce24 -> a -> Encrypted a 681 m <- sequenceMessage $ transcode encipher msg
676encryptMessage skey destKey n a = ToxCrypto.encrypt secret plain 682 return (m, rpath)
677 where
678 secret = computeSharedSecret skey destKey n
679 plain = encodePlain a
680 683
681decrypt :: TransportCrypto -> OnionMessage Encrypted -> OnionDestination r -> IO (Either String (OnionMessage Identity, OnionDestination r)) 684decrypt :: TransportCrypto -> OnionMessage Encrypted -> OnionDestination r -> IO (Either String (OnionMessage Identity, OnionDestination r))
682decrypt crypto msg addr = do 685decrypt crypto msg addr = do
683 (skey,pkey) <- selectKey crypto msg addr 686 (skey,pkey) <- selectKey crypto msg addr
687 let decipher1 :: Serialize a =>
688 TransportCrypto -> SecretKey -> PublicKey -> Nonce24
689 -> Either (PublicKey,Encrypted a) (Asymm (Encrypted a))
690 -> (IO ∘ Either String ∘ Identity) a
691 decipher1 crypto k pk n d = Composed $ do
692 secret <- lookupSharedSecret crypto k pk n
693 let ciphered = either snd asymmData d
694 return $ Composed $ do
695 plain <- ToxCrypto.decrypt secret ciphered
696 Identity <$> decodePlain plain
697 decipher :: Serialize a
698 => Nonce24 -> Either (Encrypted a) (Asymm (Encrypted a))
699 -> (IO ∘ Either String ∘ Identity) a
700 decipher = (\n -> decipher1 crypto skey pkey n . left (senderkey addr))
701 foo <- sequenceMessage $ transcode decipher msg
684 return $ do 702 return $ do
685 msg <- sequenceMessage $ transcode (\n -> decryptMessage (skey,pkey) n . left (senderkey addr)) msg 703 msg <- sequenceMessage foo
686 Right (msg, addr) 704 Right (msg, addr)
687 705
688senderkey :: OnionDestination r -> t -> (PublicKey, t) 706senderkey :: OnionDestination r -> t -> (PublicKey, t)
@@ -696,16 +714,17 @@ dhtKey :: TransportCrypto -> (SecretKey,PublicKey)
696dhtKey crypto = (transportSecret &&& transportPublic) crypto 714dhtKey crypto = (transportSecret &&& transportPublic) crypto
697 715
698decryptMessage :: Serialize x => 716decryptMessage :: Serialize x =>
699 (SecretKey,PublicKey) 717 TransportCrypto
718 -> (SecretKey,PublicKey)
700 -> Nonce24 719 -> Nonce24
701 -> Either (PublicKey, Encrypted x) 720 -> Either (PublicKey, Encrypted x)
702 (Asymm (Encrypted x)) 721 (Asymm (Encrypted x))
703 -> (Either String ∘ Identity) x 722 -> IO ((Either String ∘ Identity) x)
704decryptMessage crypto n arg = plain $ ToxCrypto.decrypt secret e 723decryptMessage crypto (sk,pk) n arg = do
705 where 724 let (sender,e) = either id (senderKey &&& asymmData) arg
706 secret = computeSharedSecret (fst crypto) sender n 725 plain = Composed . fmap Identity . (>>= decodePlain)
707 (sender,e) = either id (senderKey &&& asymmData) arg 726 secret <- lookupSharedSecret crypto sk sender n
708 plain = Composed . fmap Identity . (>>= decodePlain) 727 return $ plain $ ToxCrypto.decrypt secret e
709 728
710 729
711sequenceMessage :: Applicative m => OnionMessage (m ∘ f) -> m (OnionMessage f) 730sequenceMessage :: Applicative m => OnionMessage (m ∘ f) -> m (OnionMessage f)
@@ -732,37 +751,41 @@ data OnionRoute = OnionRoute
732 , routeNodeC :: NodeInfo 751 , routeNodeC :: NodeInfo
733 } 752 }
734 753
735wrapForRoute :: OnionMessage Encrypted -> NodeInfo -> OnionRoute -> OnionRequest N0 754wrapForRoute :: TransportCrypto -> OnionMessage Encrypted -> NodeInfo -> OnionRoute -> IO (OnionRequest N0)
736wrapForRoute msg ni r = 755wrapForRoute crypto msg ni r = do
737 -- We needn't use the same nonce value here, but I think it is safe to do so. 756 -- We needn't use the same nonce value here, but I think it is safe to do so.
738 let nonce = msgNonce msg 757 let nonce = msgNonce msg
739 in OnionRequest 758 fwd <- wrapOnion crypto (routeAliasA r)
740 { onionNonce = nonce 759 nonce
741 , onionForward = wrapOnion (routeAliasA r) 760 (id2key . nodeId $ routeNodeA r)
742 nonce 761 (nodeAddr $ routeNodeB r)
743 (id2key . nodeId $ routeNodeA r) 762 =<< wrapOnion crypto (routeAliasB r)
744 (nodeAddr $ routeNodeB r) 763 nonce
745 $ wrapOnion (routeAliasB r) 764 (id2key . nodeId $ routeNodeB r)
746 nonce 765 (nodeAddr $ routeNodeC r)
747 (id2key . nodeId $ routeNodeB r) 766 =<< wrapOnion crypto (routeAliasC r)
748 (nodeAddr $ routeNodeC r) 767 nonce
749 $ wrapOnion (routeAliasC r) 768 (id2key . nodeId $ routeNodeC r)
750 nonce 769 (nodeAddr ni)
751 (id2key . nodeId $ routeNodeC r) 770 (NotForwarded msg)
752 (nodeAddr ni) 771 return OnionRequest
753 $ NotForwarded msg 772 { onionNonce = nonce
754 , pathFromOwner = NoReturnPath 773 , onionForward = fwd
755 } 774 , pathFromOwner = NoReturnPath
775 }
756 776
757wrapOnion :: Serialize (Forwarding n msg) => 777wrapOnion :: Serialize (Forwarding n msg) =>
758 SecretKey 778 TransportCrypto
779 -> SecretKey
759 -> Nonce24 780 -> Nonce24
760 -> PublicKey 781 -> PublicKey
761 -> SockAddr 782 -> SockAddr
762 -> Forwarding n msg 783 -> Forwarding n msg
763 -> Forwarding (S n) msg 784 -> IO (Forwarding (S n) msg)
764wrapOnion skey nonce destkey saddr fwd = 785wrapOnion crypto skey nonce destkey saddr fwd = do
765 Forwarding (toPublic skey) $ encryptMessage skey destkey nonce (Addressed saddr fwd) 786 let plain = encodePlain $ Addressed saddr fwd
787 secret <- lookupSharedSecret crypto skey destkey nonce
788 return $ Forwarding (toPublic skey) $ ToxCrypto.encrypt secret plain
766 789
767 790
768-- TODO 791-- TODO
@@ -827,28 +850,29 @@ parseDataToRoute
827parseDataToRoute crypto (OnionToRouteResponse dta, od) = do 850parseDataToRoute crypto (OnionToRouteResponse dta, od) = do
828 ks <- atomically $ readTVar $ userKeys crypto 851 ks <- atomically $ readTVar $ userKeys crypto
829 852
830 let eOuter = do 853 omsg0 <- decryptMessage crypto (rendezvousSecret crypto,rendezvousPublic crypto)
831 fmap runIdentity 854 (asymmNonce dta)
832 $ uncomposed 855 (Right dta) -- using Asymm{senderKey} as remote key
833 $ decryptMessage (rendezvousSecret crypto,rendezvousPublic crypto) 856 let eOuter = fmap runIdentity $ uncomposed omsg0
834 (asymmNonce dta) 857
835 (Right dta) -- using Asymm{senderKey} as remote key 858 anyRight [] f = return $ Left "parseDataToRoute: no user key"
836 859 anyRight (x:xs) f = f x >>= either (const $ anyRight xs f) (return . Right)
837 -- TODO: We don't currently have a way to look up which user key we 860
838 -- announced using along this onion route. Therefore, for now, we will 861 -- TODO: We don't currently have a way to look up which user key we
839 -- try all our user keys to see if any can decrypt the packet. 862 -- announced using along this onion route. Therefore, for now, we will
840 eInners = flip map ks $ \(sk,pk) -> do 863 -- try all our user keys to see if any can decrypt the packet.
841 dtr <- eOuter 864 eInner <- case eOuter of
842 omsg <- fmap runIdentity 865 Left e -> return $ Left e
843 $ uncomposed 866 Right dtr -> anyRight ks $ \(sk,pk) -> do
844 $ decryptMessage (sk,pk) 867 omsg0 <- decryptMessage crypto
868 (sk,pk)
845 (asymmNonce dta) 869 (asymmNonce dta)
846 (Left (dataFromKey dtr, dataToRoute dtr)) 870 (Left (dataFromKey dtr, dataToRoute dtr))
847 return (pk,dtr,omsg) 871 return $ do
848 872 omsg <- fmap runIdentity . uncomposed $ omsg0
849 eInner = foldr (<|>) (Left "no user key") eInners 873 Right (pk,dtr,omsg)
850 874
851 e = do 875 let e = do
852 (pk,dtr,omsg) <- eInner 876 (pk,dtr,omsg) <- eInner
853 return ( (pk, omsg) 877 return ( (pk, omsg)
854 , AnnouncedRendezvous 878 , AnnouncedRendezvous
@@ -875,10 +899,12 @@ encodeDataToRoute crypto ((me,omsg), AnnouncedRendezvous toxid (Rendezvous pub n
875 let (sk,pk) = case asel of 899 let (sk,pk) = case asel of
876 AnnouncingAlias sk pk -> (sk,pk) 900 AnnouncingAlias sk pk -> (sk,pk)
877 _ -> (onionAliasSecret crypto, onionAliasPublic crypto) 901 _ -> (onionAliasSecret crypto, onionAliasPublic crypto)
878 let plain = DataToRoute { dataFromKey = pk 902 innerSecret <- lookupSharedSecret crypto sk toxid nonce
879 , dataToRoute = encryptMessage sk toxid nonce omsg 903 let plain = encodePlain $ DataToRoute { dataFromKey = pk
880 } 904 , dataToRoute = ToxCrypto.encrypt innerSecret $ encodePlain omsg
881 let dta = encryptMessage (onionAliasSecret crypto) pub nonce plain 905 }
906 outerSecret <- lookupSharedSecret crypto (onionAliasSecret crypto) pub nonce
907 let dta = ToxCrypto.encrypt outerSecret plain
882 hPutStrLn stderr $ unlines 908 hPutStrLn stderr $ unlines
883 [ "encodeDataToRoute me=" ++ show (key2id me) 909 [ "encodeDataToRoute me=" ++ show (key2id me)
884 , " dhtpk=" ++ case omsg of 910 , " dhtpk=" ++ case omsg of