1-- | 2-- Module : Network.TLS.Record.Writing 3-- License : BSD-style 4-- Maintainer : Vincent Hanquez <vincent@snarc.org> 5-- Stability : experimental 6-- Portability : unknown 7-- 8-- TLS record layer in Tx direction 9-- 10module Network.TLS.Record.Writing 11 ( encodeRecord 12 , encodeRecord13 13 , sendBytes 14 ) where 15 16import Network.TLS.Cap 17import Network.TLS.Cipher 18import Network.TLS.Context.Internal 19import Network.TLS.Hooks 20import Network.TLS.Imports 21import Network.TLS.Packet 22import Network.TLS.Parameters 23import Network.TLS.Record 24import Network.TLS.State 25import Network.TLS.Struct 26 27import Control.Concurrent.MVar 28import Control.Monad.State.Strict 29import qualified Data.ByteString as B 30 31encodeRecord :: Context -> Record Plaintext -> IO (Either TLSError ByteString) 32encodeRecord ctx = prepareRecord ctx . encodeRecordM 33 34-- before TLS 1.1, the block cipher IV is made of the residual of the previous block, 35-- so we use cstIV as is, however in other case we generate an explicit IV 36prepareRecord :: Context -> RecordM a -> IO (Either TLSError a) 37prepareRecord ctx f = do 38 ver <- usingState_ ctx (getVersionWithDefault $ maximum $ supportedVersions $ ctxSupported ctx) 39 txState <- readMVar $ ctxTxState ctx 40 let sz = case stCipher txState of 41 Nothing -> 0 42 Just cipher -> if hasRecordIV $ bulkF $ cipherBulk cipher 43 then bulkIVSize $ cipherBulk cipher 44 else 0 -- to not generate IV 45 if hasExplicitBlockIV ver && sz > 0 46 then do newIV <- getStateRNG ctx sz 47 runTxState ctx (modify (setRecordIV newIV) >> f) 48 else runTxState ctx f 49 50encodeRecordM :: Record Plaintext -> RecordM ByteString 51encodeRecordM record = do 52 erecord <- engageRecord record 53 let (hdr, content) = recordToRaw erecord 54 return $ B.concat [ encodeHeader hdr, content ] 55 56---------------------------------------------------------------- 57 58encodeRecord13 :: Context -> Record Plaintext -> IO (Either TLSError ByteString) 59encodeRecord13 ctx = prepareRecord13 ctx . encodeRecordM 60 61prepareRecord13 :: Context -> RecordM a -> IO (Either TLSError a) 62prepareRecord13 = runTxState 63 64---------------------------------------------------------------- 65 66sendBytes :: Context -> ByteString -> IO () 67sendBytes ctx dataToSend = do 68 withLog ctx $ \logging -> loggingIOSent logging dataToSend 69 contextSend ctx dataToSend 70