packages feed

cipher-aes128 0.6.4 → 0.7

raw patch · 7 files changed

+184/−32 lines, 7 filesdep ~bytestring

Dependency ranges changed: bytestring

Files

Crypto/Cipher/AES128.hs view
@@ -1,17 +1,27 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE RecordWildCards #-} module Crypto.Cipher.AES128-  ( AESKey128, AESKey192, AESKey256+  ( -- * Key types with crypto-api instances+    AESKey128, AESKey192, AESKey256   , BlockCipher(..), buildKeyIO, zeroIV+    -- * GCM Operations+  , makeGCMCtx, aesKeyToGCM, GCMCtx, AuthTag(..), AES_GCM+  , Crypto.Cipher.AES128.encryptGCM+  , Crypto.Cipher.AES128.decryptGCM   ) where -import Crypto.Cipher.AES128.Internal+import Crypto.Cipher.AES128.Internal as I import Crypto.Classes+import Data.Function (on) import Control.Monad (when) import Data.Serialize import Data.Tagged+import Data.Word (Word8) import Foreign.Ptr import Foreign.ForeignPtr+import Foreign.Marshal.Alloc as F import System.IO.Unsafe+import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Internal as B import qualified Data.ByteString.Unsafe as B@@ -147,3 +157,128 @@             return (ct,IV newIV)     {-# INLINE ctr #-}     unCtr = ctr++-- GCM Routines+maxTagLen :: Int+maxTagLen = 16++data AuthTag = AuthTag { unAuthTag :: ByteString }++-- | A tuple of key and precomputed data for use by GCM+data GCMCtx k = GCMCtx { gcmkey :: k+                       , gcmpc  :: GCMpc+                       }++instance Eq AuthTag where+    (==)  = constTimeEq `on` unAuthTag++-- A super-class indicating which keys can be used with GCMCtx.+class (BlockCipher k, GetExpanded k) => AES_GCM k where+instance AES_GCM AESKey128+instance AES_GCM AESKey192+instance AES_GCM AESKey256++-- | Given key material produce a context useful for GCM operations+makeGCMCtx :: AES_GCM k => ByteString -> Maybe (GCMCtx k)+makeGCMCtx = fmap aesKeyToGCM . buildKey++-- | Given an AESKey produce a GCM Context.+aesKeyToGCM :: AES_GCM k => k -> GCMCtx k+aesKeyToGCM k = GCMCtx k (I.precomputeGCMdata k)++-- |Encrypts multiple-of-block-sized input, returning a bytestring and tag.+encryptGCM :: AES_GCM k+           => GCMCtx k+           -> ByteString -- ^ IV+           -> ByteString -- ^ Plaintext+           -> ByteString -- ^ AAD+           -> (ByteString, AuthTag)+encryptGCM key iv pt aad = unsafePerformIO $ do+ B.unsafeUseAsCString pt  $ \ptPtr  -> do+  B.unsafeUseAsCString iv  $ \ivPtr  -> do+   B.unsafeUseAsCString aad $ \aadPtr -> do+    ctPtr  <- F.mallocBytes (B.length pt)+    tagPtr <- F.mallocBytes maxTagLen+    encryptGCMPtr key+                  (castPtr ivPtr) (B.length iv)+                  (castPtr ptPtr) (B.length pt)+                  (castPtr aadPtr) (B.length aad)+                  (castPtr ctPtr)+                  (castPtr tagPtr)+    ctBS  <- B.unsafePackMallocCStringLen (castPtr ctPtr, B.length pt)+    tagBS <- B.unsafePackMallocCStringLen (castPtr tagPtr, maxTagLen)+    return (ctBS, AuthTag tagBS)++-- Encrypts multiple-of-block-sized input, filling a pointer with the+-- result of [ctr, ct, tag].+encryptGCMPtr :: AES_GCM k+           => GCMCtx k+           -> Ptr Word8 -- ^ IV+           -> Int       -- ^ IV Length+           -> Ptr Word8 -- ^ Plaintext buffer+           -> Int       -- ^ Plaintext length+           -> Ptr Word8 -- ^ AAD buffer+           -> Int       -- ^ AAD Length+           -> Ptr Word8 -- ^ ciphertext buffer (at least encBytes large)+           -> Ptr Word8 -- ^ Tag buffer (always allocated to max length)+           -> IO ()+encryptGCMPtr (GCMCtx {..}) ivPtr ivLen+                             ptPtr ptLen+                             aadPtr aadLen+                             ctPtr+                             tagPtr =+ do I.encryptGCM gcmkey gcmpc+                   (castPtr ivPtr)  (fromIntegral ivLen)+                   (castPtr aadPtr) (fromIntegral aadLen)+                   (castPtr ptPtr)  (fromIntegral ptLen)+                   (castPtr ctPtr)+                   (castPtr tagPtr)++-- | Decrypts multiple-of-block-sized input, returing a bytestring of the+-- [ctr, ct, tag].+decryptGCM :: AES_GCM k+           => GCMCtx k+           -> ByteString -- ^ IV+           -> ByteString -- ^ Ciphertext+           -> ByteString -- ^ AAD+           -> (ByteString, AuthTag)+           -- ^ Plaintext and incremented context (or an error)+decryptGCM gcmdata iv ct aad = unsafePerformIO $ do+ let ivLen     = B.length iv+     tagLen    = maxTagLen+     ctLen     = B.length ct+ B.unsafeUseAsCString iv  $ \ivPtr  -> do+  B.unsafeUseAsCString ct  $ \ctPtr  -> do+   B.unsafeUseAsCString aad $ \aadPtr -> do+    tagPtr     <- F.mallocBytes tagLen+    ptPtr      <- F.mallocBytes ctLen+    decryptGCM_ptr gcmdata+                   (castPtr ivPtr)   ivLen+                   (castPtr ctPtr)   ctLen+                   (castPtr aadPtr) (B.length aad)+                   (castPtr ptPtr)+                   (castPtr tagPtr)+    tagBS      <- B.unsafePackMallocCStringLen (castPtr tagPtr,tagLen)+    ptBS       <- B.unsafePackMallocCStringLen (castPtr ptPtr, ctLen)+    return (ptBS, AuthTag tagBS)++decryptGCM_ptr :: AES_GCM k+               => GCMCtx k+               -> Ptr Word8 -> Int -- IV+               -> Ptr Word8 -> Int -- CT+               -> Ptr Word8 -> Int -- AAD+               -> Ptr Word8        -- Plaintext+               -> Ptr Word8        -- Tag+               -> IO ()+decryptGCM_ptr (GCMCtx {..})+               ivPtr ivLen+               ctPtr ctLen+               aadPtr aadLen+               ptPtr+               tagPtr =+    I.decryptGCM gcmkey gcmpc+                   ivPtr  (fromIntegral ivLen)+                   aadPtr (fromIntegral aadLen)+                   ctPtr  (fromIntegral ctLen)+                   ptPtr+                   tagPtr
Crypto/Cipher/AES128/Internal.hs view
@@ -12,6 +12,8 @@         , cipherOnlyGCM         , decipherOnlyGCM         , finishGCM, aadGCM+        -- * Internal, will not be exported in a near-future release.+        , GetExpanded         ) where  import Foreign.Ptr@@ -20,6 +22,7 @@ import Foreign.Marshal.Alloc import Data.Word import Data.Bits (shiftL, (.|.))+import System.IO.Unsafe  -- AES Bindings data AESKeyStruct@@ -49,6 +52,9 @@  type AESGcmPtr = Ptr GCMStruct data GCMStruct++-- Store the key, the precomputed GCM data, and the current IV by way of+-- a foreign pointer data GCM k = GCM { _gcmFP   :: GCMpc                  , _keyFP   :: k                  , _ctxFP2  :: ForeignPtr CTXStruct@@ -283,7 +289,7 @@             => k             -> IO (GCM k) generateGCM keyStruct = do-    gcmPC <- precomputeGCMdata keyStruct+    let gcmPC = precomputeGCMdata keyStruct     withForeignPtr (expandedKey keyStruct) $ \k -> do       c <- c_allocate_ctx       allocaBytes 12 $ \ivPtr -> withGCMpc gcmPC $ \g -> do@@ -293,8 +299,8 @@       return (GCM gcmPC keyStruct cFP) {-# INLINE generateGCM #-} -precomputeGCMdata :: GetExpanded k => k -> IO GCMpc-precomputeGCMdata k = do+precomputeGCMdata :: GetExpanded k => k -> GCMpc+precomputeGCMdata k = unsafePerformIO $ do     withForeignPtr (expandedKey k) $ \kp -> do         g <- c_allocate_gcm         c_gcm_init g kp@@ -381,13 +387,13 @@     c_decrypt_ctr pt p iv niv ct (fromIntegral len)  encryptGCM :: GetExpanded k-           => k-           -> GCMpc-           -> Ptr Word8 -> Word32 -- IV-           -> Ptr Word8 -> Word32 -- AAD-           -> Ptr Word8 -> Word32 -- PT-           -> Ptr Word8 -- CT-           -> Ptr Word8 -- Tag+           => k                   -- AES{128,192,256}+           -> GCMpc               -- Precomputed GCM Data+           -> Ptr Word8 -> Word32 -- IV, len+           -> Ptr Word8 -> Word32 -- AAD, len+           -> Ptr Word8 -> Word32 -- PT, len+           -> Ptr Word8 -- CT  (out)+           -> Ptr Word8 -- Tag (128 bits out)            -> IO () encryptGCM (expandedKey -> k) (GCMpc g) iv ivLen aad aadLen pt ptLen ct tag =     withForeignPtr k $ \kp ->@@ -397,11 +403,11 @@ decryptGCM :: GetExpanded k            => k            -> GCMpc-           -> Ptr Word8 -> Word32 -- IV-           -> Ptr Word8 -> Word32 -- AAD-           -> Ptr Word8 -> Word32 -- CT-           -> Ptr Word8 -- PT-           -> Ptr Word8 -- Tag+           -> Ptr Word8 -> Word32 -- IV, len+           -> Ptr Word8 -> Word32 -- AAD, len+           -> Ptr Word8 -> Word32 -- CT, len+           -> Ptr Word8           -- PT (out)+           -> Ptr Word8           -- Tag (out)            -> IO () decryptGCM (expandedKey -> k) (GCMpc g) iv ivLen aad aadLen ct ctLen pt tag =     withForeignPtr k $ \kp ->
cbits/aes.c view
@@ -34,6 +34,7 @@ #include "bitfn.h" #include <string.h> #include <stdio.h>+#include <stdlib.h>  #include "gf.h" #include "aes_x86ni.h"@@ -43,9 +44,9 @@ void tmd_aes_generic_encrypt_cbc(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_decrypt_cbc(aes_block *output, const aes_key *key, const aes_block *ivini, aes_block *newIV, const aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_encrypt_ctr(uint8_t *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const uint8_t *input, uint32_t length);-void tmd_aes_generic_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,+void tmd_aes_generic_encrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit,                              uint32_t spoint, aes_block *input, uint32_t nb_blocks);-void tmd_aes_generic_decrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,+void tmd_aes_generic_decrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit,                              uint32_t spoint, aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_gcm_encrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX); void tmd_aes_generic_gcm_decrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX);@@ -118,7 +119,7 @@         [DECRYPT_GCM_256]   = tmd_aes_generic_gcm_decrypt, }; -typedef void (*init_f)(const aes_key *, uint8_t *, uint8_t);+typedef void (*init_f)(aes_key *, const uint8_t *, uint8_t); typedef void (*ecb_f)(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks); typedef void (*cbc_f)(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *niv, const aes_block *input, uint32_t nb_blocks); typedef void (*ctr_f)(uint8_t *output, const aes_key *key, const aes_block *iv, aes_block *niv, const uint8_t *input, uint32_t length);@@ -152,7 +153,7 @@ #define aes_decrypt_block(o,k,i) \         (((block_f) (tmd_branch_table[DECRYPT_BLOCK_128 + k->strength]))(o,k,i)) #else-#define GET_INIT(strenght) tmd_aes_generic_init+#define GET_INIT(strength) tmd_aes_generic_init #define GET_ECB_ENCRYPT(strength) tmd_aes_generic_encrypt_ecb #define GET_ECB_DECRYPT(strength) tmd_aes_generic_decrypt_ecb #define GET_CBC_ENCRYPT(strength) tmd_aes_generic_encrypt_cbc@@ -291,14 +292,14 @@         e(output, key, iv, newIV, input, len); } -void tmd_aes_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,+void tmd_aes_encrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit,                      uint32_t spoint, aes_block *input, uint32_t nb_blocks) {         xts_f e = GET_XTS_ENCRYPT(k1->strength);         e(output, k1, k2, dataunit, spoint, input, nb_blocks); } -void tmd_aes_decrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,+void tmd_aes_decrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit,                      uint32_t spoint, aes_block *input, uint32_t nb_blocks) {         tmd_aes_generic_decrypt_xts(output, k1, k2, dataunit, spoint, input, nb_blocks);@@ -329,7 +330,8 @@         aes_encrypt_block(&gcm->h, key, &gcm->h); } -void tmd_aes_ctx_init(const aes_gcm *gcm, aes_ctx *ctx, const aes_key *key, const uint8_t *iv, uint32_t len)+void tmd_aes_ctx_init(const aes_gcm *gcm, aes_ctx *ctx+        , const aes_key *key, const uint8_t *iv, uint32_t len) {         ctx->length_aad = 0;         ctx->length_input = 0;@@ -485,7 +487,7 @@             block128_copy(newIV, &block); } -void tmd_aes_generic_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,+void tmd_aes_generic_encrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit,                              uint32_t spoint, aes_block *input, uint32_t nb_blocks) {         aes_block block, tweak;@@ -505,7 +507,7 @@         } } -void tmd_aes_generic_decrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,+void tmd_aes_generic_decrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit,                              uint32_t spoint, aes_block *input, uint32_t nb_blocks) {         aes_block block, tweak;
cbits/aes.h view
@@ -80,9 +80,9 @@ void tmd_aes_encrypt_ctr(uint8_t *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const uint8_t *input, uint32_t len); void tmd_aes_gen_ctr(aes_block *output, const aes_key *key, aes_block *iv, uint32_t nb_blocks); -void tmd_aes_encrypt_xts(aes_block *output, aes_key *key, aes_key *key2, aes_block *sector,+void tmd_aes_encrypt_xts(aes_block *output, const aes_key *key, aes_key *key2, aes_block *sector,                      uint32_t spoint, aes_block *input, uint32_t nb_blocks);-void tmd_aes_decrypt_xts(aes_block *output, aes_key *key, aes_key *key2, aes_block *sector,+void tmd_aes_decrypt_xts(aes_block *output, const aes_key *key, aes_key *key2, aes_block *sector,                      uint32_t spoint, aes_block *input, uint32_t nb_blocks);  void tmd_aes_gcm_init(aes_gcm *gcm, const aes_key *key);
cbits/aes_x86ni.c view
@@ -63,7 +63,7 @@ 	return _mm_xor_si128(key, keygened); } -void tmd_aes_ni_init(aes_key *key, uint8_t *ikey, uint8_t size)+void tmd_aes_ni_init(aes_key *key, const uint8_t *ikey, uint8_t size) { 	__m128i k[28]; 	uint64_t *out = (uint64_t *) key->data;
cbits/aes_x86ni.h view
@@ -49,7 +49,7 @@ } #endif -void tmd_aes_ni_init(aes_key *key, uint8_t *origkey, uint8_t size);+void tmd_aes_ni_init(aes_key *key, const uint8_t *origkey, uint8_t size); void tmd_aes_ni_encrypt_block128(aes_block *out, aes_key *key, aes_block *in); void tmd_aes_ni_encrypt_block256(aes_block *out, aes_key *key, aes_block *in); void tmd_aes_ni_decrypt_block128(aes_block *out, aes_key *key, aes_block *in);
cipher-aes128.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                cipher-aes128-version:             0.6.4+version:             0.7 synopsis:            AES and common modes using AES-NI when available. description:         Cipher-aes128 is an implementation of AES and common modes of operation.  It borrows Hanquez's C AES code (see 'cipher-aes') but                      is unique due to including compile-time detection of@@ -18,6 +18,8 @@ homepage:            https://github.com/TomMD/cipher-aes128 bug-reports:         https://github.com/TomMD/cipher-aes128/issues build-type:          Custom+-- build-type:          Simple+-- ^^^ For HaLVM cabal-version:       >=1.12  extra-source-files:       ./cbits/*.h, ./cbits/*.c@@ -27,6 +29,10 @@   description: Build a program to test the AES implementation   default: False +flag halvm+    description: The HaLVM target+    default: False+ library   default-language:    Haskell2010   exposed-modules:     Crypto.Cipher.AES128, Crypto.Cipher.AES128.Internal@@ -43,7 +49,10 @@                      , ./cbits/cpu.c                      , ./cbits/gf.c   include-dirs:        cbits/-  cc-options: -g+  cc-options:+  if flag(halvm)+    cc-options: -maes -mpclmul -mssse3 -DWITH_AESNI+    cpp-options: -DWITH_AESNI -maes -mpclmul -mssse3   -- None by default cc-options:          -mssse3 -maes -mpclmul  source-repository head