1{-# LANGUAGE ForeignFunctionInterface #-} 2{-# LANGUAGE ViewPatterns #-} 3{-# LANGUAGE MultiParamTypeClasses #-} 4{-# LANGUAGE BangPatterns #-} 5{-# LANGUAGE CPP #-} 6{-# LANGUAGE GeneralizedNewtypeDeriving #-} 7-- | 8-- Module : Crypto.Cipher.AES 9-- License : BSD-style 10-- Maintainer : Vincent Hanquez <vincent@snarc.org> 11-- Stability : stable 12-- Portability : good 13-- 14module Crypto.Cipher.AES 15 ( 16 -- * block cipher data types 17 AES 18 , AES128 19 , AES192 20 , AES256 21 22 -- * IV 23 , AESIV 24 , aesIV_ 25 26 -- * Authenticated encryption block cipher types 27 , AESGCM 28 29 -- * creation 30 , initAES 31 , initKey 32 33 -- * misc 34 , genCTR 35 , genCounter 36 37 -- * encryption 38 , encryptECB 39 , encryptCBC 40 , encryptCTR 41 , encryptXTS 42 , encryptGCM 43 , encryptOCB 44 45 -- * decryption 46 , decryptECB 47 , decryptCBC 48 , decryptCTR 49 , decryptXTS 50 , decryptGCM 51 , decryptOCB 52 ) where 53 54import Data.Word 55import Foreign.Ptr 56import Foreign.ForeignPtr 57import Foreign.C.Types 58import Foreign.C.String 59import Data.ByteString.Internal 60import Data.ByteString.Unsafe 61import Data.Byteable 62import qualified Data.ByteString as B 63import qualified Data.ByteString.Internal as B (ByteString(PS), mallocByteString, memcpy) 64import System.IO.Unsafe (unsafePerformIO) 65 66import Crypto.Cipher.Types 67import Data.SecureMem 68 69-- | AES Context (pre-processed key) 70newtype AES = AES SecureMem 71 72-- | AES with 128 bit key 73newtype AES128 = AES128 AES 74 75-- | AES with 192 bit key 76newtype AES192 = AES192 AES 77 78-- | AES with 256 bit key 79newtype AES256 = AES256 AES 80 81-- | AES IV is always 16 bytes 82newtype AESIV = AESIV ByteString 83 deriving (Show,Eq,Byteable) 84 85-- | convert a bytestring to an AESIV 86aesIV_ :: ByteString -> AESIV 87aesIV_ iv 88 | B.length iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ (show $ B.length iv) 89 | otherwise = AESIV iv 90 91instance Cipher AES where 92 cipherName _ = "AES" 93 cipherKeySize _ = KeySizeEnum [16,24,32] 94 cipherInit k = initAES k 95 96instance Cipher AES128 where 97 cipherName _ = "AES128" 98 cipherKeySize _ = KeySizeFixed 16 99 cipherInit k = AES128 $ initAES k 100 101instance Cipher AES192 where 102 cipherName _ = "AES192" 103 cipherKeySize _ = KeySizeFixed 24 104 cipherInit k = AES192 $ initAES k 105 106instance Cipher AES256 where 107 cipherName _ = "AES256" 108 cipherKeySize _ = KeySizeFixed 32 109 cipherInit k = AES256 $ initAES k 110 111instance BlockCipher AES where 112 blockSize _ = 16 113 ecbEncrypt = encryptECB 114 ecbDecrypt = decryptECB 115 cbcEncrypt = encryptCBC 116 cbcDecrypt = decryptCBC 117 ctrCombine = encryptCTR 118 xtsEncrypt = encryptXTS 119 xtsDecrypt = decryptXTS 120 aeadInit AEAD_GCM aes iv = Just $ AEAD aes $ AEADState $ gcmInit aes iv 121 aeadInit AEAD_OCB aes iv = Just $ AEAD aes $ AEADState $ ocbInit aes iv 122 aeadInit _ _ _ = Nothing 123 124instance AEADModeImpl AES AESGCM where 125 aeadStateAppendHeader _ = gcmAppendAAD 126 aeadStateEncrypt = gcmAppendEncrypt 127 aeadStateDecrypt = gcmAppendDecrypt 128 aeadStateFinalize = gcmFinish 129 130instance AEADModeImpl AES AESOCB where 131 aeadStateAppendHeader = ocbAppendAAD 132 aeadStateEncrypt = ocbAppendEncrypt 133 aeadStateDecrypt = ocbAppendDecrypt 134 aeadStateFinalize = ocbFinish 135 136#define INSTANCE_BLOCKCIPHER(CSTR) \ 137instance BlockCipher CSTR where \ 138 { blockSize _ = 16 \ 139 ; ecbEncrypt (CSTR aes) = encryptECB aes \ 140 ; ecbDecrypt (CSTR aes) = decryptECB aes \ 141 ; cbcEncrypt (CSTR aes) = encryptCBC aes \ 142 ; cbcDecrypt (CSTR aes) = decryptCBC aes \ 143 ; ctrCombine (CSTR aes) = encryptCTR aes \ 144 ; xtsEncrypt (CSTR aes1, CSTR aes2) = encryptXTS (aes1,aes2) \ 145 ; xtsDecrypt (CSTR aes1, CSTR aes2) = decryptXTS (aes1,aes2) \ 146 ; aeadInit AEAD_GCM cipher@(CSTR aes) iv = Just $ AEAD cipher $ AEADState $ gcmInit aes iv \ 147 ; aeadInit AEAD_OCB cipher@(CSTR aes) iv = Just $ AEAD cipher $ AEADState $ ocbInit aes iv \ 148 ; aeadInit _ _ _ = Nothing \ 149 }; \ 150\ 151instance AEADModeImpl CSTR AESGCM where \ 152 { aeadStateAppendHeader (CSTR _) gcmState bs = gcmAppendAAD gcmState bs \ 153 ; aeadStateEncrypt (CSTR aes) gcmState input = gcmAppendEncrypt aes gcmState input \ 154 ; aeadStateDecrypt (CSTR aes) gcmState input = gcmAppendDecrypt aes gcmState input \ 155 ; aeadStateFinalize (CSTR aes) gcmState len = gcmFinish aes gcmState len \ 156 }; \ 157\ 158instance AEADModeImpl CSTR AESOCB where \ 159 { aeadStateAppendHeader (CSTR aes) ocbState bs = ocbAppendAAD aes ocbState bs \ 160 ; aeadStateEncrypt (CSTR aes) ocbState input = ocbAppendEncrypt aes ocbState input \ 161 ; aeadStateDecrypt (CSTR aes) ocbState input = ocbAppendDecrypt aes ocbState input \ 162 ; aeadStateFinalize (CSTR aes) ocbState len = ocbFinish aes ocbState len \ 163 } 164 165INSTANCE_BLOCKCIPHER(AES128) 166INSTANCE_BLOCKCIPHER(AES192) 167INSTANCE_BLOCKCIPHER(AES256) 168 169-- | AESGCM State 170newtype AESGCM = AESGCM SecureMem 171 172-- | AESOCB State 173newtype AESOCB = AESOCB SecureMem 174 175sizeGCM :: Int 176sizeGCM = 80 177 178sizeOCB :: Int 179sizeOCB = 160 180 181keyToPtr :: AES -> (Ptr AES -> IO a) -> IO a 182keyToPtr (AES b) f = withSecureMemPtr b (f . castPtr) 183 184ivToPtr :: Byteable iv => iv -> (Ptr Word8 -> IO a) -> IO a 185ivToPtr iv f = withBytePtr iv (f . castPtr) 186 187ivCopyPtr :: AESIV -> (Ptr Word8 -> IO ()) -> IO AESIV 188ivCopyPtr (AESIV iv) f = do 189 newIV <- create 16 $ \newPtr -> do 190 withBytePtr iv $ \ivPtr -> B.memcpy newPtr ivPtr 16 191 withBytePtr newIV $ f 192 return $! AESIV newIV 193 194withKeyAndIV :: Byteable iv => AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a 195withKeyAndIV ctx iv f = keyToPtr ctx $ \kptr -> ivToPtr iv $ \ivp -> f kptr ivp 196 197withKey2AndIV :: Byteable iv => AES -> AES -> iv -> (Ptr AES -> Ptr AES -> Ptr Word8 -> IO a) -> IO a 198withKey2AndIV key1 key2 iv f = 199 keyToPtr key1 $ \kptr1 -> keyToPtr key2 $ \kptr2 -> ivToPtr iv $ \ivp -> f kptr1 kptr2 ivp 200 201withGCMKeyAndCopySt :: AES -> AESGCM -> (Ptr AESGCM -> Ptr AES -> IO a) -> IO (a, AESGCM) 202withGCMKeyAndCopySt aes (AESGCM gcmSt) f = 203 keyToPtr aes $ \aesPtr -> do 204 newSt <- secureMemCopy gcmSt 205 a <- withSecureMemPtr newSt $ \gcmStPtr -> f (castPtr gcmStPtr) aesPtr 206 return (a, AESGCM newSt) 207 208withNewGCMSt :: AESGCM -> (Ptr AESGCM -> IO ()) -> IO AESGCM 209withNewGCMSt (AESGCM gcmSt) f = withSecureMemCopy gcmSt (f . castPtr) >>= \sm2 -> return (AESGCM sm2) 210 211withOCBKeyAndCopySt :: AES -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO a) -> IO (a, AESOCB) 212withOCBKeyAndCopySt aes (AESOCB gcmSt) f = 213 keyToPtr aes $ \aesPtr -> do 214 newSt <- secureMemCopy gcmSt 215 a <- withSecureMemPtr newSt $ \gcmStPtr -> f (castPtr gcmStPtr) aesPtr 216 return (a, AESOCB newSt) 217 218-- | Initialize a new context with a key 219-- 220-- Key need to be of length 16, 24 or 32 bytes. any other values will cause undefined behavior 221initAES :: Byteable b => b -> AES 222initAES k 223 | len == 16 = initWithRounds 10 224 | len == 24 = initWithRounds 12 225 | len == 32 = initWithRounds 14 226 | otherwise = error "AES: not a valid key length (valid=16,24,32)" 227 where len = byteableLength k 228 initWithRounds nbR = AES $ unsafeCreateSecureMem (16+2*2*16*nbR) aesInit 229 aesInit ptr = withBytePtr k $ \ikey -> 230 c_aes_init (castPtr ptr) (castPtr ikey) (fromIntegral len) 231 232{-# DEPRECATED initKey "use initAES" #-} 233initKey :: Byteable b => b -> AES 234initKey = initAES 235 236-- | encrypt using Electronic Code Book (ECB) 237{-# NOINLINE encryptECB #-} 238encryptECB :: AES -> ByteString -> ByteString 239encryptECB = doECB c_aes_encrypt_ecb 240 241-- | encrypt using Cipher Block Chaining (CBC) 242{-# NOINLINE encryptCBC #-} 243encryptCBC :: Byteable iv 244 => AES -- ^ AES Context 245 -> iv -- ^ Initial vector of AES block size 246 -> ByteString -- ^ plaintext 247 -> ByteString -- ^ ciphertext 248encryptCBC = doCBC c_aes_encrypt_cbc 249 250-- | generate a counter mode pad. this is generally xor-ed to an input 251-- to make the standard counter mode block operations. 252-- 253-- if the length requested is not a multiple of the block cipher size, 254-- more data will be returned, so that the returned bytestring is 255-- a multiple of the block cipher size. 256{-# NOINLINE genCTR #-} 257genCTR :: Byteable iv 258 => AES -- ^ Cipher Key. 259 -> iv -- ^ usually a 128 bit integer. 260 -> Int -- ^ length of bytes required. 261 -> ByteString 262genCTR ctx iv len 263 | len <= 0 = B.empty 264 | byteableLength iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ (show $ byteableLength iv) 265 | otherwise = unsafeCreate (nbBlocks * 16) generate 266 where generate o = withKeyAndIV ctx iv $ \k i -> c_aes_gen_ctr (castPtr o) k i (fromIntegral nbBlocks) 267 (nbBlocks',r) = len `quotRem` 16 268 nbBlocks = if r == 0 then nbBlocks' else nbBlocks' + 1 269 270-- | generate a counter mode pad. this is generally xor-ed to an input 271-- to make the standard counter mode block operations. 272-- 273-- if the length requested is not a multiple of the block cipher size, 274-- more data will be returned, so that the returned bytestring is 275-- a multiple of the block cipher size. 276-- 277-- Similiar to 'genCTR' but also return the next IV for continuation 278{-# NOINLINE genCounter #-} 279genCounter :: AES 280 -> AESIV 281 -> Int 282 -> (ByteString, AESIV) 283genCounter ctx iv len 284 | len <= 0 = (B.empty, iv) 285 | otherwise = unsafePerformIO $ do 286 fptr <- B.mallocByteString outputLength 287 newIv <- withForeignPtr fptr $ \o -> 288 keyToPtr ctx $ \k -> 289 ivCopyPtr iv $ \i -> do 290 c_aes_gen_ctr_cont (castPtr o) k i (fromIntegral nbBlocks) 291 let !out = B.PS fptr 0 outputLength 292 return $! (out `seq` newIv `seq` (out, newIv)) 293 where 294 (nbBlocks',r) = len `quotRem` 16 295 nbBlocks = if r == 0 then nbBlocks' else nbBlocks' + 1 296 outputLength = nbBlocks * 16 297 298{- TODO: when genCTR has same AESIV requirements for IV, add the following rules: 299 - RULES "snd . genCounter" forall ctx iv len . snd (genCounter ctx iv len) = genCTR ctx iv len 300 -} 301 302-- | encrypt using Counter mode (CTR) 303-- 304-- in CTR mode encryption and decryption is the same operation. 305{-# NOINLINE encryptCTR #-} 306encryptCTR :: Byteable iv 307 => AES -- ^ AES Context 308 -> iv -- ^ initial vector of AES block size (usually representing a 128 bit integer) 309 -> ByteString -- ^ plaintext input 310 -> ByteString -- ^ ciphertext output 311encryptCTR ctx iv input 312 | len <= 0 = B.empty 313 | byteableLength iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ (show $ byteableLength iv) 314 | otherwise = unsafeCreate len doEncrypt 315 where doEncrypt o = withKeyAndIV ctx iv $ \k v -> unsafeUseAsCString input $ \i -> 316 c_aes_encrypt_ctr (castPtr o) k v i (fromIntegral len) 317 len = B.length input 318 319-- | encrypt using Galois counter mode (GCM) 320-- return the encrypted bytestring and the tag associated 321-- 322-- note: encrypted data is identical to CTR mode in GCM, however 323-- a tag is also computed. 324{-# NOINLINE encryptGCM #-} 325encryptGCM :: Byteable iv 326 => AES -- ^ AES Context 327 -> iv -- ^ IV initial vector of any size 328 -> ByteString -- ^ data to authenticate (AAD) 329 -> ByteString -- ^ data to encrypt 330 -> (ByteString, AuthTag) -- ^ ciphertext and tag 331encryptGCM = doGCM gcmAppendEncrypt 332 333-- | encrypt using OCB v3 334-- return the encrypted bytestring and the tag associated 335{-# NOINLINE encryptOCB #-} 336encryptOCB :: Byteable iv 337 => AES -- ^ AES Context 338 -> iv -- ^ IV initial vector of any size 339 -> ByteString -- ^ data to authenticate (AAD) 340 -> ByteString -- ^ data to encrypt 341 -> (ByteString, AuthTag) -- ^ ciphertext and tag 342encryptOCB = doOCB ocbAppendEncrypt 343 344-- | encrypt using XTS 345-- 346-- the first key is the normal block encryption key 347-- the second key is used for the initial block tweak 348{-# NOINLINE encryptXTS #-} 349encryptXTS :: Byteable iv 350 => (AES,AES) -- ^ AES cipher and tweak context 351 -> iv -- ^ a 128 bits IV, typically a sector or a block offset in XTS 352 -> Word32 -- ^ number of rounds to skip, also seen a 16 byte offset in the sector or block. 353 -> ByteString -- ^ input to encrypt 354 -> ByteString -- ^ output encrypted 355encryptXTS = doXTS c_aes_encrypt_xts 356 357-- | decrypt using Electronic Code Book (ECB) 358{-# NOINLINE decryptECB #-} 359decryptECB :: AES -> ByteString -> ByteString 360decryptECB = doECB c_aes_decrypt_ecb 361 362-- | decrypt using Cipher block chaining (CBC) 363{-# NOINLINE decryptCBC #-} 364decryptCBC :: Byteable iv => AES -> iv -> ByteString -> ByteString 365decryptCBC = doCBC c_aes_decrypt_cbc 366 367-- | decrypt using Counter mode (CTR). 368-- 369-- in CTR mode encryption and decryption is the same operation. 370decryptCTR :: Byteable iv 371 => AES -- ^ AES Context 372 -> iv -- ^ initial vector, usually representing a 128 bit integer 373 -> ByteString -- ^ ciphertext input 374 -> ByteString -- ^ plaintext output 375decryptCTR = encryptCTR 376 377-- | decrypt using XTS 378{-# NOINLINE decryptXTS #-} 379decryptXTS :: Byteable iv 380 => (AES,AES) -- ^ AES cipher and tweak context 381 -> iv -- ^ a 128 bits IV, typically a sector or a block offset in XTS 382 -> Word32 -- ^ number of rounds to skip, also seen a 16 byte offset in the sector or block. 383 -> ByteString -- ^ input to decrypt 384 -> ByteString -- ^ output decrypted 385decryptXTS = doXTS c_aes_decrypt_xts 386 387-- | decrypt using Galois Counter Mode (GCM) 388{-# NOINLINE decryptGCM #-} 389decryptGCM :: Byteable iv 390 => AES -- ^ Key 391 -> iv -- ^ IV initial vector of any size 392 -> ByteString -- ^ data to authenticate (AAD) 393 -> ByteString -- ^ data to decrypt 394 -> (ByteString, AuthTag) -- ^ plaintext and tag 395decryptGCM = doGCM gcmAppendDecrypt 396 397-- | decrypt using Offset Codebook Mode (OCB) 398{-# NOINLINE decryptOCB #-} 399decryptOCB :: Byteable iv 400 => AES -- ^ Key 401 -> iv -- ^ IV initial vector of any size 402 -> ByteString -- ^ data to authenticate (AAD) 403 -> ByteString -- ^ data to decrypt 404 -> (ByteString, AuthTag) -- ^ plaintext and tag 405decryptOCB = doOCB ocbAppendDecrypt 406 407{-# INLINE doECB #-} 408doECB :: (Ptr b -> Ptr AES -> CString -> CUInt -> IO ()) 409 -> AES -> ByteString -> ByteString 410doECB f ctx input 411 | r /= 0 = error $ "Encryption error: input length must be a multiple of block size (16). Its length is: " ++ (show len) 412 | otherwise = unsafeCreate len $ \o -> 413 keyToPtr ctx $ \k -> 414 unsafeUseAsCString input $ \i -> 415 f (castPtr o) k i (fromIntegral nbBlocks) 416 where (nbBlocks, r) = len `quotRem` 16 417 len = (B.length input) 418 419{-# INLINE doCBC #-} 420doCBC :: Byteable iv 421 => (Ptr b -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()) 422 -> AES -> iv -> ByteString -> ByteString 423doCBC f ctx iv input 424 | len == 0 = B.empty 425 | byteableLength iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ (show $ byteableLength iv) 426 | r /= 0 = error $ "Encryption error: input length must be a multiple of block size (16). Its length is: " ++ (show len) 427 | otherwise = unsafeCreate len $ \o -> 428 withKeyAndIV ctx iv $ \k v -> 429 unsafeUseAsCString input $ \i -> 430 f (castPtr o) k v i (fromIntegral nbBlocks) 431 where (nbBlocks, r) = len `quotRem` 16 432 len = B.length input 433 434{-# INLINE doXTS #-} 435doXTS :: Byteable iv 436 => (Ptr b -> Ptr AES -> Ptr AES -> Ptr Word8 -> CUInt -> CString -> CUInt -> IO ()) 437 -> (AES, AES) 438 -> iv 439 -> Word32 440 -> ByteString 441 -> ByteString 442doXTS f (key1,key2) iv spoint input 443 | len == 0 = B.empty 444 | r /= 0 = error $ "Encryption error: input length must be a multiple of block size (16) for now. Its length is: " ++ (show len) 445 | otherwise = unsafeCreate len $ \o -> withKey2AndIV key1 key2 iv $ \k1 k2 v -> unsafeUseAsCString input $ \i -> 446 f (castPtr o) k1 k2 v (fromIntegral spoint) i (fromIntegral nbBlocks) 447 where (nbBlocks, r) = len `quotRem` 16 448 len = B.length input 449 450------------------------------------------------------------------------ 451-- GCM 452------------------------------------------------------------------------ 453 454{-# INLINE doGCM #-} 455doGCM :: Byteable iv 456 => (AES -> AESGCM -> ByteString -> (ByteString, AESGCM)) 457 -> AES 458 -> iv 459 -> ByteString 460 -> ByteString 461 -> (ByteString, AuthTag) 462doGCM f ctx iv aad input = (output, tag) 463 where tag = gcmFinish ctx after 16 464 (output, after) = f ctx afterAAD input 465 afterAAD = gcmAppendAAD ini aad 466 ini = gcmInit ctx iv 467 468-- | initialize a gcm context 469{-# NOINLINE gcmInit #-} 470gcmInit :: Byteable iv => AES -> iv -> AESGCM 471gcmInit ctx iv = unsafePerformIO $ do 472 sm <- createSecureMem sizeGCM $ \gcmStPtr -> 473 withKeyAndIV ctx iv $ \k v -> 474 c_aes_gcm_init (castPtr gcmStPtr) k v (fromIntegral $ byteableLength iv) 475 return $ AESGCM sm 476 477-- | append data which is going to just be authentified to the GCM context. 478-- 479-- need to happen after initialization and before appending encryption/decryption data. 480{-# NOINLINE gcmAppendAAD #-} 481gcmAppendAAD :: AESGCM -> ByteString -> AESGCM 482gcmAppendAAD gcmSt input = unsafePerformIO doAppend 483 where doAppend = 484 withNewGCMSt gcmSt $ \gcmStPtr -> 485 unsafeUseAsCString input $ \i -> 486 c_aes_gcm_aad gcmStPtr i (fromIntegral $ B.length input) 487 488-- | append data to encrypt and append to the GCM context 489-- 490-- bytestring need to be multiple of AES block size, unless it's the last call to this function. 491-- need to happen after AAD appending, or after initialization if no AAD data. 492{-# NOINLINE gcmAppendEncrypt #-} 493gcmAppendEncrypt :: AES -> AESGCM -> ByteString -> (ByteString, AESGCM) 494gcmAppendEncrypt ctx gcm input = unsafePerformIO $ withGCMKeyAndCopySt ctx gcm doEnc 495 where len = B.length input 496 doEnc gcmStPtr aesPtr = 497 create len $ \o -> 498 unsafeUseAsCString input $ \i -> 499 c_aes_gcm_encrypt (castPtr o) gcmStPtr aesPtr i (fromIntegral len) 500 501-- | append data to decrypt and append to the GCM context 502-- 503-- bytestring need to be multiple of AES block size, unless it's the last call to this function. 504-- need to happen after AAD appending, or after initialization if no AAD data. 505{-# NOINLINE gcmAppendDecrypt #-} 506gcmAppendDecrypt :: AES -> AESGCM -> ByteString -> (ByteString, AESGCM) 507gcmAppendDecrypt ctx gcm input = unsafePerformIO $ withGCMKeyAndCopySt ctx gcm doDec 508 where len = B.length input 509 doDec gcmStPtr aesPtr = 510 create len $ \o -> 511 unsafeUseAsCString input $ \i -> 512 c_aes_gcm_decrypt (castPtr o) gcmStPtr aesPtr i (fromIntegral len) 513 514-- | Generate the Tag from GCM context 515{-# NOINLINE gcmFinish #-} 516gcmFinish :: AES -> AESGCM -> Int -> AuthTag 517gcmFinish ctx gcm taglen = AuthTag $ B.take taglen computeTag 518 where computeTag = unsafeCreate 16 $ \t -> 519 withGCMKeyAndCopySt ctx gcm (c_aes_gcm_finish (castPtr t)) >> return () 520 521------------------------------------------------------------------------ 522-- OCB v3 523------------------------------------------------------------------------ 524 525{-# INLINE doOCB #-} 526doOCB :: Byteable iv 527 => (AES -> AESOCB -> ByteString -> (ByteString, AESOCB)) 528 -> AES 529 -> iv 530 -> ByteString 531 -> ByteString 532 -> (ByteString, AuthTag) 533doOCB f ctx iv aad input = (output, tag) 534 where tag = ocbFinish ctx after 16 535 (output, after) = f ctx afterAAD input 536 afterAAD = ocbAppendAAD ctx ini aad 537 ini = ocbInit ctx iv 538 539-- | initialize an ocb context 540{-# NOINLINE ocbInit #-} 541ocbInit :: Byteable iv => AES -> iv -> AESOCB 542ocbInit ctx iv = unsafePerformIO $ do 543 sm <- createSecureMem sizeOCB $ \ocbStPtr -> 544 withKeyAndIV ctx iv $ \k v -> 545 c_aes_ocb_init (castPtr ocbStPtr) k v (fromIntegral $ byteableLength iv) 546 return $ AESOCB sm 547 548-- | append data which is going to just be authentified to the OCB context. 549-- 550-- need to happen after initialization and before appending encryption/decryption data. 551{-# NOINLINE ocbAppendAAD #-} 552ocbAppendAAD :: AES -> AESOCB -> ByteString -> AESOCB 553ocbAppendAAD ctx ocb input = unsafePerformIO (snd `fmap` withOCBKeyAndCopySt ctx ocb doAppend) 554 where doAppend ocbStPtr aesPtr = 555 unsafeUseAsCString input $ \i -> 556 c_aes_ocb_aad ocbStPtr aesPtr i (fromIntegral $ B.length input) 557 558-- | append data to encrypt and append to the OCB context 559-- 560-- bytestring need to be multiple of AES block size, unless it's the last call to this function. 561-- need to happen after AAD appending, or after initialization if no AAD data. 562{-# NOINLINE ocbAppendEncrypt #-} 563ocbAppendEncrypt :: AES -> AESOCB -> ByteString -> (ByteString, AESOCB) 564ocbAppendEncrypt ctx ocb input = unsafePerformIO $ withOCBKeyAndCopySt ctx ocb doEnc 565 where len = B.length input 566 doEnc ocbStPtr aesPtr = 567 create len $ \o -> 568 unsafeUseAsCString input $ \i -> 569 c_aes_ocb_encrypt (castPtr o) ocbStPtr aesPtr i (fromIntegral len) 570 571-- | append data to decrypt and append to the OCB context 572-- 573-- bytestring need to be multiple of AES block size, unless it's the last call to this function. 574-- need to happen after AAD appending, or after initialization if no AAD data. 575{-# NOINLINE ocbAppendDecrypt #-} 576ocbAppendDecrypt :: AES -> AESOCB -> ByteString -> (ByteString, AESOCB) 577ocbAppendDecrypt ctx ocb input = unsafePerformIO $ withOCBKeyAndCopySt ctx ocb doDec 578 where len = B.length input 579 doDec ocbStPtr aesPtr = 580 create len $ \o -> 581 unsafeUseAsCString input $ \i -> 582 c_aes_ocb_decrypt (castPtr o) ocbStPtr aesPtr i (fromIntegral len) 583 584-- | Generate the Tag from OCB context 585{-# NOINLINE ocbFinish #-} 586ocbFinish :: AES -> AESOCB -> Int -> AuthTag 587ocbFinish ctx ocb taglen = AuthTag $ B.take taglen computeTag 588 where computeTag = unsafeCreate 16 $ \t -> 589 withOCBKeyAndCopySt ctx ocb (c_aes_ocb_finish (castPtr t)) >> return () 590 591------------------------------------------------------------------------ 592foreign import ccall "aes.h aes_initkey" 593 c_aes_init :: Ptr AES -> CString -> CUInt -> IO () 594 595------------------------------------------------------------------------ 596foreign import ccall "aes.h aes_encrypt_ecb" 597 c_aes_encrypt_ecb :: CString -> Ptr AES -> CString -> CUInt -> IO () 598 599foreign import ccall "aes.h aes_decrypt_ecb" 600 c_aes_decrypt_ecb :: CString -> Ptr AES -> CString -> CUInt -> IO () 601 602------------------------------------------------------------------------ 603foreign import ccall "aes.h aes_encrypt_cbc" 604 c_aes_encrypt_cbc :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO () 605 606foreign import ccall "aes.h aes_decrypt_cbc" 607 c_aes_decrypt_cbc :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO () 608 609------------------------------------------------------------------------ 610foreign import ccall "aes.h aes_encrypt_xts" 611 c_aes_encrypt_xts :: CString -> Ptr AES -> Ptr AES -> Ptr Word8 -> CUInt -> CString -> CUInt -> IO () 612 613foreign import ccall "aes.h aes_decrypt_xts" 614 c_aes_decrypt_xts :: CString -> Ptr AES -> Ptr AES -> Ptr Word8 -> CUInt -> CString -> CUInt -> IO () 615 616------------------------------------------------------------------------ 617foreign import ccall "aes.h aes_gen_ctr" 618 c_aes_gen_ctr :: CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO () 619 620foreign import ccall unsafe "aes.h aes_gen_ctr_cont" 621 c_aes_gen_ctr_cont :: CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO () 622 623foreign import ccall "aes.h aes_encrypt_ctr" 624 c_aes_encrypt_ctr :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO () 625 626------------------------------------------------------------------------ 627foreign import ccall "aes.h aes_gcm_init" 628 c_aes_gcm_init :: Ptr AESGCM -> Ptr AES -> Ptr Word8 -> CUInt -> IO () 629 630foreign import ccall "aes.h aes_gcm_aad" 631 c_aes_gcm_aad :: Ptr AESGCM -> CString -> CUInt -> IO () 632 633foreign import ccall "aes.h aes_gcm_encrypt" 634 c_aes_gcm_encrypt :: CString -> Ptr AESGCM -> Ptr AES -> CString -> CUInt -> IO () 635 636foreign import ccall "aes.h aes_gcm_decrypt" 637 c_aes_gcm_decrypt :: CString -> Ptr AESGCM -> Ptr AES -> CString -> CUInt -> IO () 638 639foreign import ccall "aes.h aes_gcm_finish" 640 c_aes_gcm_finish :: CString -> Ptr AESGCM -> Ptr AES -> IO () 641 642------------------------------------------------------------------------ 643foreign import ccall "aes.h aes_ocb_init" 644 c_aes_ocb_init :: Ptr AESOCB -> Ptr AES -> Ptr Word8 -> CUInt -> IO () 645 646foreign import ccall "aes.h aes_ocb_aad" 647 c_aes_ocb_aad :: Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO () 648 649foreign import ccall "aes.h aes_ocb_encrypt" 650 c_aes_ocb_encrypt :: CString -> Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO () 651 652foreign import ccall "aes.h aes_ocb_decrypt" 653 c_aes_ocb_decrypt :: CString -> Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO () 654 655foreign import ccall "aes.h aes_ocb_finish" 656 c_aes_ocb_finish :: CString -> Ptr AESOCB -> Ptr AES -> IO () 657