module Crypto.Cipher.AES128 ( AESKey ) where import Crypto.Cipher.AES128.Internal import Crypto.Classes import Crypto.Types import Control.Monad (when) import Data.Serialize import Data.Tagged import Foreign.Ptr import Foreign.ForeignPtr import System.IO.Unsafe import qualified Data.ByteString as B import qualified Data.ByteString.Internal as B import qualified Data.ByteString.Unsafe as B instance Serialize AESKey where put k = do let RKey l h = (rawKey k) putWord64be h putWord64be l get = do b <- getByteString 16 case buildKey b of Nothing -> fail "Invalid key on 'get'" Just k -> return k instance BlockCipher AESKey where blockSize = Tagged 128 keyLength = Tagged 128 buildKey bs | B.length bs >= 16 = unsafePerformIO $ B.unsafeUseAsCString bs $ \ptr -> do k <- generateKey (castPtr ptr) return (Just k) | otherwise = Nothing encryptBlock k b = unsafePerformIO $ do B.unsafeUseAsCStringLen b $ \(inP,len) -> do B.create (B.length b) $ \outP -> do encryptECB k (castPtr outP) (castPtr inP) (len`div`blkSize) decryptBlock k b = unsafePerformIO $ do B.unsafeUseAsCStringLen b $ \(inP,len) -> do B.create (B.length b) $ \outP -> do decryptECB k (castPtr outP) (castPtr inP) (len`div`blkSize) ctr k (IV bs) pt = unsafePerformIO $ do B.unsafeUseAsCStringLen pt $ \(inP, len) -> do B.unsafeUseAsCStringLen bs $ \(ivP, ivLen) -> do when (ivLen /= (blockSizeBytes .::. k)) (error "Cipher-AES128: IV wrong length! They type system would have/should have caught this if you didn't use the IV constructor...") newIVFP <- B.mallocByteString ivLen ct <- B.create len $ \outP -> withForeignPtr newIVFP $ \newIVP -> do encryptCTR k (castPtr ivP) (castPtr newIVP) (castPtr outP) (castPtr inP) len let newIV = B.fromForeignPtr newIVFP 0 ivLen return (ct,IV newIV) unCtr = ctr blkSize :: Int blkSize = 16