diff options
author | joe <joe@jerkface.net> | 2017-11-05 01:25:36 -0500 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-11-05 01:25:36 -0500 |
commit | 8039d812b7ea8ae566f8873452ac34597336ddfc (patch) | |
tree | 2b28e0b1ea90a4eb1122c723b82e580873a33cde /src/Network/Tox/Onion | |
parent | cb7337dc453131864f2692ef202230f2e7ae740b (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')
-rw-r--r-- | src/Network/Tox/Onion/Transport.hs | 178 |
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 | |||
231 | routeId nid = RouteId $ mod (hash nid) 12 | 231 | routeId nid = RouteId $ mod (hash nid) 12 |
232 | 232 | ||
233 | 233 | ||
234 | encodeOnionAddr :: (NodeInfo -> RouteId -> IO (Maybe OnionRoute)) | 234 | encodeOnionAddr :: 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)) |
237 | encodeOnionAddr _ (msg,OnionToOwner ni p) = | 238 | encodeOnionAddr 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 ) |
240 | encodeOnionAddr getRoute (msg,OnionDestination x ni Nothing) = do | 241 | encodeOnionAddr 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 |
244 | encodeOnionAddr getRoute (msg,OnionDestination _ ni (Just rid)) = do | 245 | encodeOnionAddr 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))) |
509 | peelOnion crypto nonce (Forwarding k fwd) = | 512 | peelOnion 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 | ||
512 | handleOnionResponse :: (KnownPeanoNat n, Sized (ReturnPath n), Serialize (ReturnPath n)) => proxy (S n) -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionResponse (S n) -> IO a | 515 | handleOnionResponse :: (KnownPeanoNat n, Sized (ReturnPath n), Serialize (ReturnPath n)) => proxy (S n) -> TransportCrypto -> SockAddr -> UDPTransport -> IO a -> OnionResponse (S n) -> IO a |
513 | handleOnionResponse proxy crypto saddr udp kont (OnionResponse path msg) = do | 516 | handleOnionResponse 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) |
663 | selectKey crypto msg rpath = return $ aliasKey crypto rpath | 666 | selectKey crypto msg rpath = return $ aliasKey crypto rpath |
664 | 667 | ||
665 | encrypt :: TransportCrypto -> OnionMessage Identity -> OnionDestination r -> IO (OnionMessage Encrypted, OnionDestination r) | 668 | encrypt :: TransportCrypto |
669 | -> OnionMessage Identity | ||
670 | -> OnionDestination r | ||
671 | -> IO (OnionMessage Encrypted, OnionDestination r) | ||
666 | encrypt crypto msg rpath = do | 672 | encrypt 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 | |
674 | encryptMessage :: 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 |
676 | encryptMessage 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 | ||
681 | decrypt :: TransportCrypto -> OnionMessage Encrypted -> OnionDestination r -> IO (Either String (OnionMessage Identity, OnionDestination r)) | 684 | decrypt :: TransportCrypto -> OnionMessage Encrypted -> OnionDestination r -> IO (Either String (OnionMessage Identity, OnionDestination r)) |
682 | decrypt crypto msg addr = do | 685 | decrypt 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 | ||
688 | senderkey :: OnionDestination r -> t -> (PublicKey, t) | 706 | senderkey :: OnionDestination r -> t -> (PublicKey, t) |
@@ -696,16 +714,17 @@ dhtKey :: TransportCrypto -> (SecretKey,PublicKey) | |||
696 | dhtKey crypto = (transportSecret &&& transportPublic) crypto | 714 | dhtKey crypto = (transportSecret &&& transportPublic) crypto |
697 | 715 | ||
698 | decryptMessage :: Serialize x => | 716 | decryptMessage :: 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) |
704 | decryptMessage crypto n arg = plain $ ToxCrypto.decrypt secret e | 723 | decryptMessage 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 | ||
711 | sequenceMessage :: Applicative m => OnionMessage (m ∘ f) -> m (OnionMessage f) | 730 | sequenceMessage :: 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 | ||
735 | wrapForRoute :: OnionMessage Encrypted -> NodeInfo -> OnionRoute -> OnionRequest N0 | 754 | wrapForRoute :: TransportCrypto -> OnionMessage Encrypted -> NodeInfo -> OnionRoute -> IO (OnionRequest N0) |
736 | wrapForRoute msg ni r = | 755 | wrapForRoute 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 | ||
757 | wrapOnion :: Serialize (Forwarding n msg) => | 777 | wrapOnion :: 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) |
764 | wrapOnion skey nonce destkey saddr fwd = | 785 | wrapOnion 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 | |||
827 | parseDataToRoute crypto (OnionToRouteResponse dta, od) = do | 850 | parseDataToRoute 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 |