mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
core: use 12 bytes IV for WebRTC frame encryption with AES-GCM (#1951)
* core: use 12 bytes IV for WebRTC frame encryption with AES-GCM * refactor
This commit is contained in:
committed by
GitHub
parent
6eddb5f30f
commit
50b90c4814
@@ -1,10 +1,15 @@
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
|
||||
module Simplex.Chat.Mobile.WebRTC where
|
||||
module Simplex.Chat.Mobile.WebRTC (
|
||||
cChatEncryptMedia,
|
||||
cChatDecryptMedia,
|
||||
chatEncryptMedia,
|
||||
chatDecryptMedia,
|
||||
reservedSize,
|
||||
) where
|
||||
|
||||
import Control.Monad.Except
|
||||
import qualified Crypto.Cipher.Types as AES
|
||||
import Crypto.Random (getRandomBytes)
|
||||
import Data.Bifunctor (bimap)
|
||||
import qualified Data.ByteArray as BA
|
||||
import qualified Data.ByteString as B
|
||||
@@ -41,44 +46,37 @@ cTransformMedia f cKey cFrame cFrameLen = do
|
||||
|
||||
chatEncryptMedia :: ByteString -> ByteString -> ExceptT String IO ByteString
|
||||
chatEncryptMedia keyStr frame = do
|
||||
checkFrameLen frame
|
||||
len <- checkFrameLen frame
|
||||
key <- decodeKey keyStr
|
||||
iv <- liftIO $ getRandomBytes ivSize
|
||||
let (frame', _) = B.splitAt (B.length frame - reservedSize) frame
|
||||
(tag, frame'') <- withExceptT show $ C.encryptAESNoPad key (C.IV $ iv <> ivPad) frame'
|
||||
let authTag = BA.convert $ C.unAuthTag tag
|
||||
pure $ frame'' <> authTag <> iv
|
||||
iv <- liftIO C.randomGCMIV
|
||||
(tag, frame') <- withExceptT show $ C.encryptAESNoPad key iv $ B.take len frame
|
||||
pure $ frame' <> BA.convert (C.unAuthTag tag) <> C.unGCMIV iv
|
||||
|
||||
chatDecryptMedia :: ByteString -> ByteString -> ExceptT String IO ByteString
|
||||
chatDecryptMedia keyStr frame = do
|
||||
checkFrameLen frame
|
||||
len <- checkFrameLen frame
|
||||
key <- decodeKey keyStr
|
||||
let (rest, iv) = B.splitAt (B.length frame - ivSize) frame
|
||||
(frame', tag) = B.splitAt (B.length rest - C.authTagSize) rest
|
||||
let (frame', rest) = B.splitAt len frame
|
||||
(tag, iv) = B.splitAt C.authTagSize rest
|
||||
authTag = C.AuthTag $ AES.AuthTag $ BA.convert tag
|
||||
frame'' <- withExceptT show $ C.decryptAESNoPad key (C.IV $ iv <> ivPad) frame' authTag
|
||||
pure $ frame'' <> B.replicate reservedSize 0
|
||||
withExceptT show $ do
|
||||
iv' <- liftEither $ C.gcmIV iv
|
||||
frame'' <- C.decryptAESNoPad key iv' frame' authTag
|
||||
pure $ frame'' <> framePad
|
||||
|
||||
checkFrameLen :: ByteString -> ExceptT String IO ()
|
||||
checkFrameLen frame =
|
||||
when (B.length frame < reservedSize) $ throwError "frame has no [reserved space] IV and/or auth tag"
|
||||
checkFrameLen :: ByteString -> ExceptT String IO Int
|
||||
checkFrameLen frame = do
|
||||
let len = B.length frame - reservedSize
|
||||
when (len < 0) $ throwError "frame has no [reserved space for] IV and/or auth tag"
|
||||
pure len
|
||||
{-# INLINE checkFrameLen #-}
|
||||
|
||||
decodeKey :: ByteString -> ExceptT String IO C.Key
|
||||
decodeKey = liftEither . bimap ("invalid key: " <>) C.Key . U.decode
|
||||
{-# INLINE decodeKey #-}
|
||||
|
||||
authTagSize :: Int
|
||||
authTagSize = C.authTagSize
|
||||
{-# INLINE authTagSize #-}
|
||||
|
||||
ivSize :: Int
|
||||
ivSize = 12
|
||||
{-# INLINE ivSize #-}
|
||||
|
||||
ivPad :: ByteString
|
||||
ivPad = B.replicate 4 0
|
||||
|
||||
reservedSize :: Int
|
||||
reservedSize = authTagSize + ivSize
|
||||
{-# INLINE reservedSize #-}
|
||||
reservedSize = C.authTagSize + C.gcmIVSize
|
||||
|
||||
framePad :: ByteString
|
||||
framePad = B.replicate reservedSize 0
|
||||
|
||||
Reference in New Issue
Block a user