summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tox-crypto/src/Crypto/Tox.hs66
1 files changed, 38 insertions, 28 deletions
diff --git a/tox-crypto/src/Crypto/Tox.hs b/tox-crypto/src/Crypto/Tox.hs
index ea276045..04b55d94 100644
--- a/tox-crypto/src/Crypto/Tox.hs
+++ b/tox-crypto/src/Crypto/Tox.hs
@@ -294,29 +294,27 @@ encryptPayload st g =
294 g 294 g
295 295
296-- (Poly1305.State, XSalsa.State) 296-- (Poly1305.State, XSalsa.State)
297computeSharedSecret :: SecretKey -> PublicKey -> Nonce24 -> State 297computeSharedSecret :: SecretKey -> PublicKey -> Maybe (Nonce24 -> State)
298computeSharedSecret sk recipient = k `seq` \nonce -> 298computeSharedSecret sk recipient = case mk of
299 let -- cipher state 299 Just k -> Just $ \nonce ->
300 st0 = XSalsa.initialize 20 k nonce 300 let -- cipher state
301 -- Poly1305 key 301 st0 = XSalsa.initialize 20 k nonce
302 (rs, crypt) = XSalsa.combine st0 zs where Nonce32 zs = zeros32 302 -- Poly1305 key
303 -- Since rs is 32 bytes, this pattern should never fail... 303 (rs, crypt) = XSalsa.combine st0 zs where Nonce32 zs = zeros32
304 Cryptonite.CryptoPassed hash = Poly1305.initialize rs 304 -- Since rs is 32 bytes, this pattern should never fail...
305 in State hash crypt 305 Cryptonite.CryptoPassed hash = Poly1305.initialize rs
306 in State hash crypt
307 Nothing -> Nothing
306 where 308 where
307 -- diffie helman 309 -- diffie helman
308#if MIN_VERSION_cryptonite(0,24,0) 310#if MIN_VERSION_cryptonite(0,24,0)
309 -- TODO: Handle failure. 311 -- Note This *does* fail.
310 -- Failure was observed... 312 shared = Cryptonite.maybeCryptoError $ ecdh (Proxy :: Proxy Curve_X25519) sk recipient
311 -- Reproduce by issuing tox command "ping 192.168.10.1:33446" without specifying
312 -- the public key portion of the node id.
313 -- "Irrefutable pattern failed for pattern CryptoPassed shared"
314 Cryptonite.CryptoPassed shared = ecdh (Proxy :: Proxy Curve_X25519) sk recipient
315#else 313#else
316 shared = ecdh (Proxy :: Proxy Curve_X25519) sk recipient 314 shared = Just $ ecdh (Proxy :: Proxy Curve_X25519) sk recipient
317#endif 315#endif
318 -- shared secret XSalsa key 316 -- shared secret XSalsa key
319 k = hsalsa20 shared zeros24 317 mk = fmap (`hsalsa20` zeros24) shared
320 318
321unsafeFirstWord64 :: ByteArrayAccess ba => ba -> Word64 319unsafeFirstWord64 :: ByteArrayAccess ba => ba -> Word64
322unsafeFirstWord64 ba = unsafeDupablePerformIO $ BA.withByteArray ba peek 320unsafeFirstWord64 ba = unsafeDupablePerformIO $ BA.withByteArray ba peek
@@ -366,6 +364,15 @@ lookupNonceFunction c@(TransportCrypto{secretsCache}) sk recipient = do
366 now <- getPOSIXTime 364 now <- getPOSIXTime
367 atomically $ lookupNonceFunctionSTM now c sk recipient 365 atomically $ lookupNonceFunctionSTM now c sk recipient
368 366
367-- | Dummy, used to indicate computeSharedSecret failure. This is a way to provide
368-- the old non-failing interface compatibly.
369dummyState :: State
370dummyState = State hash xsalsa
371 where
372 xsalsa = XSalsa.initialize 20 zeros32 zeros24
373 -- Since zeros32 is 32 bytes, this pattern should never fail...
374 Cryptonite.CryptoPassed hash = Poly1305.initialize zeros32
375
369{-# INLINE lookupNonceFunctionSTM #-} 376{-# INLINE lookupNonceFunctionSTM #-}
370-- | This version of 'lookupNonceFunction' is STM instead of IO, this means if some later part of 377-- | This version of 'lookupNonceFunction' is STM instead of IO, this means if some later part of
371-- of the transaction fails, we may end up forgoing a computation that could have been cached. 378-- of the transaction fails, we may end up forgoing a computation that could have been cached.
@@ -375,18 +382,21 @@ lookupNonceFunctionSTM :: POSIXTime -> TransportCrypto -> SecretKey -> PublicKey
375lookupNonceFunctionSTM now TransportCrypto{secretsCache} sk recipient = do 382lookupNonceFunctionSTM now TransportCrypto{secretsCache} sk recipient = do
376 mm <- readTVar $ sharedSecret secretsCache 383 mm <- readTVar $ sharedSecret secretsCache
377 case MM.lookup' recipient mm of 384 case MM.lookup' recipient mm of
378 Nothing -> do 385 Nothing -> case computeSharedSecret sk recipient of
379 let miss = computeSharedSecret sk recipient 386 Just miss -> do
380 writeTVar (sharedSecret secretsCache) 387 writeTVar (sharedSecret secretsCache)
381 (MM.insertTake' 160 recipient (MM.singleton' sk miss (Down now)) (Down now) mm) 388 (MM.insertTake' 160 recipient (MM.singleton' sk miss (Down now)) (Down now) mm)
382 return miss 389 return miss
390 Nothing -> return $ const dummyState
383 Just (stamp,smm) -> do 391 Just (stamp,smm) -> do
384 let (r,v) = case MM.lookup' sk smm of 392 let (r,mv) = case MM.lookup' sk smm of
385 Nothing | let miss = computeSharedSecret sk recipient 393 Nothing | Just miss <- computeSharedSecret sk recipient
386 -> (miss, MM.insertTake' 3 sk miss (Down now) smm) 394 -> (miss, Just $ MM.insertTake' 3 sk miss (Down now) smm)
387 Just (stamp2,hit) -> (hit , MM.insert' sk hit (Down now) smm) 395 Nothing -> (const dummyState, Nothing)
388 writeTVar (sharedSecret secretsCache) 396 Just (stamp2,hit) -> (hit , Just $ MM.insert' sk hit (Down now) smm)
389 (MM.insertTake' 160 recipient v (Down now) mm) 397 forM_ mv $ \v -> do
398 writeTVar (sharedSecret secretsCache)
399 (MM.insertTake' 160 recipient v (Down now) mm)
390 return r 400 return r
391 401
392 402