{-# LANGUAGE OverloadedStrings #-} module WebRTCTests where import Control.Monad.Except import Crypto.Random (getRandomBytes) import qualified Data.ByteString.Base64.URL as U import qualified Data.ByteString.Char8 as B import Foreign.StablePtr import Simplex.Chat.Mobile import Simplex.Chat.Mobile.WebRTC import qualified Simplex.Messaging.Crypto as C import System.FilePath (()) import Test.Hspec webRTCTests :: SpecWith FilePath webRTCTests = describe "WebRTC crypto" $ do it "encrypts and decrypts media" $ \tmp -> do Right c <- chatMigrateInit (tmp "1") "" "yesUp" cc <- newStablePtr c key <- U.encode <$> getRandomBytes 32 frame <- getRandomBytes 1000 Right frame' <- runExceptT $ chatEncryptMedia cc key $ frame <> B.replicate reservedSize '\NUL' B.length frame' `shouldBe` B.length frame + reservedSize Right frame'' <- runExceptT $ chatDecryptMedia key frame' frame'' `shouldBe` frame <> B.replicate reservedSize '\NUL' it "should fail on invalid frame size" $ \tmp -> do Right c <- chatMigrateInit (tmp "1") "" "yesUp" cc <- newStablePtr c key <- U.encode <$> getRandomBytes 32 frame <- getRandomBytes 10 runExceptT (chatEncryptMedia cc key frame) `shouldReturn` Left "frame has no [reserved space for] IV and/or auth tag" runExceptT (chatDecryptMedia key frame) `shouldReturn` Left "frame has no [reserved space for] IV and/or auth tag" it "should fail on invalid key" $ \tmp -> do Right c <- chatMigrateInit (tmp "1") "" "yesUp" cc <- newStablePtr c let key = B.replicate 32 '#' frame <- (<> B.replicate reservedSize '\NUL') <$> getRandomBytes 100 runExceptT (chatEncryptMedia cc key frame) `shouldReturn` Left "invalid key: invalid character at offset: 0" runExceptT (chatDecryptMedia key frame) `shouldReturn` Left "invalid key: invalid character at offset: 0" it "should fail on invalid auth tag" $ \tmp -> do Right c <- chatMigrateInit (tmp "1") "" "yesUp" cc <- newStablePtr c key <- U.encode <$> getRandomBytes 32 frame <- getRandomBytes 1000 Right frame' <- runExceptT $ chatEncryptMedia cc key $ frame <> B.replicate reservedSize '\NUL' Right frame'' <- runExceptT $ chatDecryptMedia key frame' frame'' `shouldBe` frame <> B.replicate reservedSize '\NUL' let (encFrame, rest) = B.splitAt (B.length frame' - reservedSize) frame (_tag, iv) = B.splitAt C.authTagSize rest badFrame = encFrame <> B.replicate C.authTagSize '\NUL' <> iv runExceptT (chatDecryptMedia key badFrame) `shouldReturn` Left "AESDecryptError"