summaryrefslogtreecommitdiff
path: root/src/Network/Tox/Handshake.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/Tox/Handshake.hs')
-rw-r--r--src/Network/Tox/Handshake.hs125
1 files changed, 0 insertions, 125 deletions
diff --git a/src/Network/Tox/Handshake.hs b/src/Network/Tox/Handshake.hs
deleted file mode 100644
index c48b7415..00000000
--- a/src/Network/Tox/Handshake.hs
+++ /dev/null
@@ -1,125 +0,0 @@
1{-# LANGUAGE CPP #-}
2{-# LANGUAGE DeriveFunctor #-}
3{-# LANGUAGE NamedFieldPuns #-}
4{-# LANGUAGE PatternSynonyms #-}
5{-# LANGUAGE TupleSections #-}
6{-# LANGUAGE TypeOperators #-}
7module Network.Tox.Handshake where
8
9import Control.Arrow
10import Control.Concurrent.STM
11import Control.Monad
12import Crypto.Hash
13import Crypto.Tox
14import Data.Functor.Identity
15import Data.Time.Clock.POSIX
16import Network.Tox.Crypto.Transport
17import Network.Tox.DHT.Handlers (createCookieSTM)
18import Network.Tox.DHT.Transport (Cookie (..), CookieData (..))
19import Network.Tox.NodeId
20#ifdef THREAD_DEBUG
21#else
22import Control.Concurrent
23import GHC.Conc (labelThread)
24#endif
25import DPut
26import DebugTag
27
28
29anyRight :: Monad m => a -> [t] -> (t -> m (Either b b1)) -> m (Either a b1)
30anyRight e [] f = return $ Left e
31anyRight e (x:xs) f = f x >>= either (const $ anyRight e xs f) (return . Right)
32
33decryptHandshake :: TransportCrypto -> Handshake Encrypted -> IO (Either String (SecretKey,Handshake Identity))
34decryptHandshake crypto hshake@(Handshake (Cookie n24 ecookie) nonce24 encrypted) = do
35 (ukeys,symkey) <- atomically $ (,) <$> userKeys crypto
36 <*> transportSymmetric crypto
37 let seckeys = map fst ukeys
38 now <- getPOSIXTime
39 -- dput XNetCrypto "decryptHandshake: trying the following keys:"
40 -- forM_ seckeys $ \k -> dput XNetCrypto $ " " ++ show (key2id . toPublic $ k)
41 fmap join . sequence $ do -- Either Monad
42 cd@(CookieData cookieTime remotePubkey remoteDhtkey) <- decodePlain =<< decryptSymmetric symkey n24 ecookie
43 Right $ do -- IO Monad
44 decrypted <- anyRight "missing key" seckeys $ \key -> do
45 -- dput XNetCrypto $ "(NetCrypto)handshakeH: remotePubkey = " ++ show (key2id $ remotePubkey)
46 -- dput XNetCrypto $ "(NetCrypto)handshakeH: nonce24 = " ++ show nonce24
47 secret <- lookupSharedSecret crypto key remotePubkey nonce24
48 let step1 = decrypt secret encrypted
49 case step1 of
50 Left s -> do
51 -- dput XNetCrypto $ "(NetCrypto)handshakeH: (decrypt) " ++ s
52 return (Left s)
53 Right pln -> do
54 case decodePlain pln of
55 Left s -> do
56 -- dput XNetCrypto $ "(NetCrypto)handshakeH: (decodePlain) " ++ s
57 return (Left s)
58 Right x -> return (Right (key,x))
59 return $ do -- Either Monad
60 (key,hsdata@HandshakeData { baseNonce, sessionKey, cookieHash, otherCookie }) <- decrypted
61 left (asTypeOf "cookie too old") $ guard (now - fromIntegral cookieTime < 15)
62 let hinit = hashInit
63 hctx = hashUpdate hinit n24
64 hctx' = hashUpdate hctx ecookie
65 digest = hashFinalize hctx'
66 left (asTypeOf "cookie digest mismatch") $ guard (cookieHash == digest)
67 return ( key
68 , hshake { handshakeCookie = Cookie n24 (pure cd)
69 , handshakeData = pure hsdata
70 } )
71
72
73data HandshakeParams
74 = HParam
75 { hpTheirBaseNonce :: Maybe Nonce24 -- ignore and generate your own
76 , hpOtherCookie :: Cookie Encrypted
77 , hpTheirSessionKeyPublic :: Maybe PublicKey
78 , hpMySecretKey :: SecretKey
79 , hpCookieRemotePubkey :: PublicKey
80 , hpCookieRemoteDhtkey :: PublicKey
81 }
82
83newHandShakeData :: POSIXTime -> TransportCrypto -> Nonce24 -> HandshakeParams -> NodeInfo -> PublicKey -> STM HandshakeData
84newHandShakeData timestamp crypto basenonce hp nodeinfo mySessionPublic = do
85 let HParam {hpOtherCookie,hpMySecretKey,hpCookieRemotePubkey,hpCookieRemoteDhtkey} = hp
86 hinit = hashInit
87 Cookie n24 encrypted = hpOtherCookie
88 hctx = hashUpdate hinit n24
89 hctx' = hashUpdate hctx encrypted
90 digest = hashFinalize hctx'
91 freshCookie <- createCookieSTM timestamp crypto nodeinfo hpCookieRemotePubkey
92 return HandshakeData
93 { baseNonce = basenonce
94 , sessionKey = mySessionPublic
95 , cookieHash = digest
96 , otherCookie = freshCookie
97 }
98
99toHandshakeParams :: (SecretKey, Handshake Identity) -> HandshakeParams
100toHandshakeParams (key,hs)
101 = let hd = runIdentity $ handshakeData hs
102 Cookie _ cd0 = handshakeCookie hs
103 CookieData _ remotePublicKey remoteDhtPublicKey = runIdentity cd0
104 in HParam { hpTheirBaseNonce = Just $ baseNonce hd
105 , hpOtherCookie = otherCookie hd
106 , hpTheirSessionKeyPublic = Just $ sessionKey hd
107 , hpMySecretKey = key
108 , hpCookieRemotePubkey = remotePublicKey
109 , hpCookieRemoteDhtkey = remoteDhtPublicKey
110 }
111
112encodeHandshake :: POSIXTime
113 -> TransportCrypto
114 -> SecretKey
115 -> PublicKey
116 -> Cookie Encrypted
117 -> HandshakeData
118 -> STM (Handshake Encrypted)
119encodeHandshake timestamp crypto me them otherCookie myhandshakeData = do
120 n24 <- transportNewNonce crypto
121 state <- ($ n24) <$> lookupNonceFunctionSTM timestamp crypto me them
122 return Handshake { handshakeCookie = otherCookie
123 , handshakeNonce = n24
124 , handshakeData = encrypt state $ encodePlain myhandshakeData
125 }