packages feed

cipher-aes128 (empty) → 0.1

raw patch · 16 files changed

+1883/−0 lines, 16 filesdep +basedep +bytestringdep +cerealbuild-type:Customsetup-changed

Dependencies added: base, bytestring, cereal, crypto-api, tagged

Files

+ AUTHORS view
@@ -0,0 +1,4 @@+Vincent Hanquez implemented, in C, the AES routines.++Thomas M. DuBuisson is the original author of the implementation selection+routines in cbits/aes/aes.c and Haskell bindings.
+ Crypto/Cipher/AES128.hs view
@@ -0,0 +1,46 @@+module Crypto.Cipher.AES128+  ( AESKey+  ) where++import Crypto.Cipher.AES128.Internal+import Crypto.Classes+import Data.Serialize+import Data.Tagged+import Foreign.Ptr+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)++blkSize :: Int+blkSize = 16
+ Crypto/Cipher/AES128/Internal.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}+module Crypto.Cipher.AES128.Internal+        ( AESKey(..), RawKey(..)+        , generateKey+        , encryptECB+        , decryptECB+        , encryptGCM+        , decryptGCM+        ) where++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Data.Word+import Data.Bits (shiftL, (.|.))++-- AES Bindings+data AESKeyStruct+type AESKeyPtr = Ptr AESKeyStruct+data RawKey = RKey { lowK,highK :: {-# UNPACK #-} !Word64 }+data AESKey = AESKey { rawKey      :: !RawKey+                     , expandedKey :: ForeignPtr AESKeyStruct }++foreign import ccall unsafe "aes/aes.h generate_key128"+        c_generate_key128 :: AESKeyPtr -> Ptr Word8 -> IO ()++foreign import ccall unsafe "aes/aes.h allocate_key128"+        c_allocate_key128 :: IO AESKeyPtr++foreign import ccall unsafe "aes/aes.h &free_key128"+        c_free_key128 :: FunPtr (AESKeyPtr -> IO ())++foreign import ccall unsafe "aes/aes.h encrypt_ecb"+        c_encrypt_ecb :: AESKeyPtr -> Ptr Word8 -> Ptr Word8 -> Word32 -> IO ()++foreign import ccall unsafe "aes/aes.h decrypt_ecb"+        c_decrypt_ecb :: AESKeyPtr -> Ptr Word8 -> Ptr Word8 -> Word32 -> IO ()++foreign import ccall unsafe "aes/aes.h aes_gcm_full_encrypt"+    c_encrypt_gcm :: AESKeyPtr+                  -> Ptr Word8 -> Word32 -- ^ IV and length+                  -> Ptr Word8 -> Word32 -- ^ AAD and length+                  -> Ptr Word8 -> Word32 -- ^ PT and length+                  -> Ptr Word8 -> Ptr Word8 -- ^ Result CT and TAG+                  -> IO ()++foreign import ccall unsafe "aes/aes.h aes_gcm_full_decrypt"+    c_decrypt_gcm :: AESKeyPtr+                  -> Ptr Word8 -> Word32 -- ^ IV and length+                  -> Ptr Word8 -> Word32 -- ^ AAD and length+                  -> Ptr Word8 -> Word32 -- ^ CT and length+                  -> Ptr Word8 -> Ptr Word8 -- ^ Result PT and TAG+                  -> IO ()++blkSzC :: Word32+blkSzC = 16++-- Given a 16 byte buffer, allocate and return an AESKey+generateKey :: Ptr Word64 -- ^ Buffer of 16 bytes of key material+            -> IO AESKey+generateKey keyPtr  = do+    k <- c_allocate_key128+    c_generate_key128 k (castPtr keyPtr)+    raw <- do+            a <- peekLE (castPtr keyPtr)+            let keyPtr2 = (castPtr keyPtr) `plusPtr` sizeOf a+            b <- peekLE keyPtr2+            return (RKey a b)+    fmap (AESKey raw) (newForeignPtr c_free_key128 k)+ where+     peekLE p = do+        a1 <- peekElemOff p 0+        a2 <- peekElemOff p 1+        a3 <- peekElemOff p 2+        a4 <- peekElemOff p 3+        a5 <- peekElemOff p 4+        a6 <- peekElemOff p 5+        a7 <- peekElemOff p 6+        a8 <- peekElemOff p 7+        let a = (a1 `shiftL` 56) .|. (a2 `shiftL` 48) .|. (a3 `shiftL` 40) .|.+                (a4 `shiftL` 32) .|. (a5 `shiftL` 24) .|. (a6 `shiftL` 16) .|.+                (a7 `shiftL` 8)  .|. a8+        return a+{-# INLINE generateKey #-}++-- An encrypt function that can handle up to blks < maxBound `div` 16 :: Word32+-- simultaneous blocks.+encryptECB :: AESKey    -- ^ The key+           -> Ptr Word8 -- ^ The result buffer+           -> Ptr Word8 -- ^ The source buffer+           -> Int       -- ^ The input size in blocks+           -> IO ()+encryptECB (AESKey _ k) dst src blks = withForeignPtr k $ \p -> c_encrypt_ecb p dst src (fromIntegral blks)+{-# INLINE encryptECB #-}++decryptECB :: AESKey    -- ^ The key+           -> Ptr Word8 -- ^ The result buffer+           -> Ptr Word8 -- ^ The source buffer+           -> Int       -- ^ The input size in blocks+           -> IO ()+decryptECB (AESKey _ k) dst src blks+  | blks > fromIntegral (maxBound `div` blkSzC :: Word32) = error "Can not decrypt so many blocks at once"+  | otherwise = withForeignPtr k $ \p -> c_decrypt_ecb p dst src (fromIntegral blks)+{-# INLINE decryptECB #-}++encryptGCM :: AESKey+           -> Ptr Word8 -> Int -- IV+           -> Ptr Word8 -> Int -- AAD+           -> Ptr Word8 -> Int -- PT+           -> Ptr Word8        -- CT  (output)+           -> Ptr Word8        -- Tag (output)+           -> IO ()+encryptGCM (AESKey _ k) iv ivLen aad aadLen pt ptLen ct tag = withForeignPtr k $ \p -> do+        c_encrypt_gcm p iv (fromIntegral ivLen) aad (fromIntegral aadLen) pt (fromIntegral ptLen) ct tag+{-# INLINE encryptGCM #-}++decryptGCM :: AESKey+           -> Ptr Word8 -> Int -- IV+           -> Ptr Word8 -> Int -- AAD+           -> Ptr Word8 -> Int -- CT+           -> Ptr Word8        -- PT  (output)+           -> Ptr Word8        -- Tag (output)+           -> IO ()+decryptGCM (AESKey _ k) iv ivLen aad aadLen ct ctLen pt tag = withForeignPtr k $ \p -> do+        c_decrypt_gcm p iv (fromIntegral ivLen) aad (fromIntegral aadLen) ct (fromIntegral ctLen) pt tag+{-# INLINE decryptGCM #-}
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) Thomas DuBuisson++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,74 @@+import Distribution.Simple+import Distribution.Simple.Setup+import Distribution.PackageDescription+import Distribution.Simple.Utils+import Distribution.Simple.Program+import Distribution.Verbosity+import System.Process+import System.Directory+import System.Exit++main = defaultMainWithHooks hk+ where+ hk = simpleUserHooks { preBuild = \as fs -> do+                                        b <- (preBuild simpleUserHooks) as fs+                                        checkAndAddAES fs b }++checkAndAddAES :: BuildFlags -> HookedBuildInfo -> IO HookedBuildInfo+checkAndAddAES fs x@(m,as) = do+        b  <- canUseAesIntrinsicsFlag fs+        b2 <- haveNIInstrs fs+        let bi = maybe emptyBuildInfo id m+            op = if b && b2 then addNIintrinsicOpt else id+        return (Just (op emptyBuildInfo), as)++addNIintrinsicOpt :: BuildInfo -> BuildInfo+addNIintrinsicOpt bi = bi { ccOptions = ccOptions bi ++ ["-maes", "-mssse3", "-DHAVE_AES_INTRINSICS", "-DHAVE_NI"] }++-- Detect if we have AES NI instructions for acceleration on x86 CPUs+haveNIInstrs :: BuildFlags -> IO Bool+haveNIInstrs cf = do+        -- FIXME cf is always empty, how do we ensure we're testing the right C compiler?+        -- TODO: I am hooking Cabal at the wrong spot, need to hook one stage+        -- later!+        let prog = lookup "cc" (buildProgramPaths cf)+            cc = maybe "gcc" id prog+        withTempDirectory normal "" "testNI" $ \tmpDir -> do+         writeFile (tmpDir ++ "/testNI.c")+               (unlines ["#include <stdint.h>",+                        "/**",+                        " * Returns zero if false, non-zero otherwise",+                        " */",+                        "int cpu_has_ni()",+                        "{",+                        "uint32_t ax,bx,cx,dx,func=1;",+                        "uint32_t regs[4];",+                        "asm volatile (\"cpuid\":",+                        "\"=a\" (ax), \"=b\" (bx), \"=c\" (cx), \"=d\" (dx) : \"a\" (func));",+                        "return (cx & 0x2000000);",+                        "}",+                        "int main()",+                        "{",+                        "    if(cpu_has_ni()) return 0; else return -1;",+                        "}"]+                                )+         ec <- rawSystemExitCode normal cc ["-maes",tmpDir ++ "/testNI.c"]+         notice normal $ "Result of AES NI Test: " ++ show (ec == ExitSuccess)+         return (ec == ExitSuccess)++canUseAesIntrinsicsFlag :: BuildFlags -> IO Bool+canUseAesIntrinsicsFlag cf = do+        -- FIXME cf is always empty, how do we ensure we're testing the right C compiler?+        -- TODO: I am hooking Cabal at the wrong spot, need to hook one stage+        -- later!+        let prog = lookup "cc" (buildProgramPaths cf)+            cc = maybe "gcc" id prog+        withTempDirectory normal "" "testIntrinsic" $ \tmpDir -> do+        writeFile (tmpDir ++ "/testIntrinsic.c")+                (unlines        [ "#include <wmmintrin.h>"+                                , "int main() {"+                                , "return 0; }"+                                ])+        ec <- rawSystemExitCode normal cc ["-maes",tmpDir ++ "/testIntrinsic.c"]+        notice normal $ "Result of NI Intrinsics Test: " ++ show (ec == ExitSuccess)+        return (ec == ExitSuccess)
+ cbits/aes/LICENSE view
@@ -0,0 +1,29 @@+This license applies to the ni/* generic/* source code and associated header files.++Copyright (c) 2010-2011 Vincent Hanquez <vincent@snarc.org>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ cbits/aes/aes.c view
@@ -0,0 +1,365 @@+#include "aes_generic.h"+#include "aes.h"+#include <string.h>+#include <stdlib.h>++/* The "HAVE_NI" macro is also defined (or not) but we no longer need that+ * since we're doing a runtime detection... again. */+#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_AES_INTRINSICS) && !defined(AVOID_NI)+#define TRY_NI+#include "aes_x86ni.h"+#endif+#include "bitfn.h"+void gf_mul(block128 *a, block128 *b);++#ifdef TRY_NI+/**+ * Returns zero if false, non-zero otherwise+ */+int cpu_has_ni()+{+       uint32_t ax,bx,cx,dx,func=1;++       __asm__ volatile ("cpuid":\+           "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));+       return (cx & 0x2000000);+}+#endif++/* Allocation */+AESKey *allocate_key128()+{+        void *k=NULL;+        k = (void *)malloc(sizeof(aes_key));+        return k;+}++/* Generate Key */+#ifdef TRY_NI+void detect_and_generate_key128(AESKey *k, const uint8_t *bytes);+void (*generate_key128_ptr)(AESKey *,const uint8_t *) = &detect_and_generate_key128;++/**+ * Expand a 128 bit AES key.+ */+void generate_key128(AESKey *k, const uint8_t *bytes)+{+    (*generate_key128_ptr)(k,bytes);+}++void generate_key128_generic(AESKey *k, const uint8_t *bytes)+{+    aes_generic_init(k, bytes, 16);+}++void generate_key128_ni(AESKey *k, const uint8_t *bytes)+{+    aes_ni_init((aes_key *)k, bytes, 16);+}++void detect_and_generate_key128(AESKey *k, const uint8_t *bytes)+{+    if(cpu_has_ni()) {+            generate_key128_ptr = &generate_key128_ni;+    } else {+            generate_key128_ptr = &generate_key128_generic;+    }+    (*generate_key128_ptr)(k,bytes);+}++#else+void generate_key128(AESKey *k, const uint8_t *bytes)+{+    aes_generic_init(k, bytes, 16);+}+#endif++void free_key128(AESKey *k)+{+        memset(k, 0, sizeof(AESKey));+        free(k);+}++/* ECB Encrypt */+#ifdef TRY_NI+void detect_and_encrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr);+void (*encrypt_ecb_ptr)(const AESKey *, uint8_t *, const uint8_t *, const uint32_t) = &detect_and_encrypt_ecb;++void encrypt_ecb_ni(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+        aes_ni_encrypt_ecb(dst, (aes_key *)k, src, nr);+}++void encrypt_ecb_generic(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+    int i;+    for(i = 0; i<nr*16; i+=16) {+        aes_generic_encrypt_block+                       ( (aes_block*) dst+i+                       , k+                       , (const aes_block*)src+i);+    }+}++void encrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+        (*encrypt_ecb_ptr)(k,dst,src,nr);+}++void detect_and_encrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+        if(cpu_has_ni()) encrypt_ecb_ptr = &encrypt_ecb_ni;+        else encrypt_ecb_ptr = &encrypt_ecb_generic;+        (*encrypt_ecb_ptr)(k,dst,src,nr);+}+#else+void encrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+    int i;+    for(i = 0; i<nr*16; i+=16) {+        aes_generic_encrypt_block+                       ( (aes_block*) dst+i+                       , k+                       , (const aes_block*)src+i);+    }+}+#endif++/* ECB Decrypt */+#ifdef TRY_NI+void detect_and_decrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr);+void (*decrypt_ecb_ptr)(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr) = &detect_and_decrypt_ecb;++void decrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+        (*decrypt_ecb_ptr)(k,dst,src,nr);+}++void decrypt_ecb_ni(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+        aes_ni_decrypt_ecb(dst, (aes_key *)k, src, nr);+}++void decrypt_ecb_generic(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+    int i;+    for(i = 0; i<nr*16; i+=16) {+        aes_generic_decrypt_block ( (aes_block*) dst+i+                                  , k+                                  , (const aes_block*)src+i);+    }+}++void detect_and_decrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+        if(cpu_has_ni()) decrypt_ecb_ptr = &decrypt_ecb_ni;+        else decrypt_ecb_ptr = &decrypt_ecb_generic;+        (*decrypt_ecb_ptr)(k,dst,src,nr);+}+#else+void decrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr)+{+    int i;+    for(i = 0; i<nr*16; i+=16) {+        aes_generic_decrypt_block ( (aes_block*) dst+i+                                  , k+                                  , (const aes_block*)src+i);+    }+}+#endif+++/* GCM */+static void gcm_ghash_add(aes_gcm *gcm, block128 *b)+{+        block128_xor(&gcm->tag, b);+        gf_mul(&gcm->tag, &gcm->h);+}++void aes_gcm_init(aes_gcm *gcm, const aes_key *key, uint8_t *iv, uint32_t len)+{+        gcm->length_aad = 0;+        gcm->length_input = 0;++        block128_zero(&gcm->h);+        block128_zero(&gcm->tag);+        block128_zero(&gcm->iv);++        memcpy(&gcm->key, key, sizeof(aes_key));++        /* prepare H : encrypt_K(0^128) */+        encrypt_ecb(key, (uint8_t *)&gcm->h, (const uint8_t *)&gcm->h, 1);++        if (len == 12) {+                block128_copy_bytes(&gcm->iv, iv, 12);+                gcm->iv.b[15] = 0x01;+        } else {+                uint32_t origlen = len << 3;+                int i;+                for (; len >= 16; len -= 16, iv += 16) {+                        block128_xor(&gcm->iv, (block128 *) iv);+                        gf_mul(&gcm->iv, &gcm->h);+                }+                if (len > 0) {+                        block128_xor_bytes(&gcm->iv, iv, len);+                        gf_mul(&gcm->iv, &gcm->h);+                }+                for (i = 15; origlen; --i, origlen >>= 8)+                        gcm->iv.b[i] ^= (uint8_t) origlen;+                gf_mul(&gcm->iv, &gcm->h);+        }++        block128_copy(&gcm->civ, &gcm->iv);+}++void aes_gcm_aad(aes_gcm *gcm, uint8_t *input, uint32_t length)+{+        gcm->length_aad += length;+        for (; length >= 16; input += 16, length -= 16) {+                gcm_ghash_add(gcm, (block128 *) input);+        }+        if (length > 0) {+                aes_block tmp;+                block128_zero(&tmp);+                block128_copy_bytes(&tmp, input, length);+                gcm_ghash_add(gcm, &tmp);+        }++}++void aes_gcm_encrypt(uint8_t *output, aes_gcm *gcm, uint8_t *input, uint32_t length)+{+        aes_block out;++        gcm->length_input += length;+        for (; length >= 16; input += 16, output += 16, length -= 16) {+                block128_inc_be(&gcm->civ);++                encrypt_ecb(&gcm->key, (uint8_t *)&out, (const uint8_t *)&gcm->civ, 1);+                block128_xor(&out, (block128 *) input);+                gcm_ghash_add(gcm, &out);+                block128_copy((block128 *) output, &out);+        }+        if (length > 0) {+                aes_block tmp;+                int i;++                block128_inc_be(&gcm->civ);+                /* create e(civ) in out */+                encrypt_ecb(&gcm->key, (uint8_t *)&out, (const uint8_t *)&gcm->civ, 1);+                /* initialize a tmp as input and xor it to e(civ) */+                block128_zero(&tmp);+                block128_copy_bytes(&tmp, input, length);+                block128_xor_bytes(&tmp, out.b, length); ++                gcm_ghash_add(gcm, &tmp);++                for (i = 0; i < length; i++) {+                        output[i] = tmp.b[i];+                }+        }+}++void aes_gcm_decrypt(uint8_t *output, aes_gcm *gcm, uint8_t *input, uint32_t length)+{+        aes_block out;++        gcm->length_input += length;+        for (; length >= 16; input += 16, output += 16, length -= 16) {+                block128_inc_be(&gcm->civ);++                encrypt_ecb(&gcm->key, (uint8_t *)&out, (const uint8_t *)&gcm->civ, 1);+                gcm_ghash_add(gcm, (block128 *) input);+                block128_xor(&out, (block128 *) input);+                block128_copy((block128 *) output, &out);+        }+        if (length > 0) {+                aes_block tmp;+                int i;++                block128_inc_be(&gcm->civ);++                block128_zero(&tmp);+                block128_copy_bytes(&tmp, input, length);+                gcm_ghash_add(gcm, &tmp);++                encrypt_ecb(&gcm->key, (uint8_t *)&out, (const uint8_t *)&gcm->civ, 1);+                block128_xor_bytes(&tmp, out.b, length); ++                for (i = 0; i < length; i++) {+                        output[i] = tmp.b[i];+                }+        }+}++void aes_gcm_finish(uint8_t *tag, aes_gcm *gcm)+{+        aes_block lblock;+        int i;++        /* tag = (tag-1 xor (lenbits(a) | lenbits(c)) ) . H */+        lblock.q[0] = cpu_to_be64(gcm->length_aad << 3);+        lblock.q[1] = cpu_to_be64(gcm->length_input << 3);+        gcm_ghash_add(gcm, &lblock);++        encrypt_ecb(&gcm->key, (uint8_t *)&lblock, (const uint8_t*)&gcm->iv, 1);+        block128_xor(&gcm->tag, &lblock);++        for (i = 0; i < 16; i++) {+                tag[i] = gcm->tag.b[i];+        }+}++void aes_gcm_full_encrypt( const AESKey *k+                         , uint8_t *iv, uint32_t ivLen+                         , uint8_t *aad, uint32_t aadLen+                         , uint8_t *pt, uint32_t ptLen+                         , uint8_t *ct, uint8_t *tag)+{+    aes_gcm gcm;+    aes_gcm_init(&gcm, k, iv, ivLen);+    aes_gcm_aad(&gcm, aad, aadLen);+    aes_gcm_encrypt(ct, &gcm,  pt, ptLen);+    aes_gcm_finish(tag, &gcm);+}++void aes_gcm_full_decrypt( const AESKey *k+                         , uint8_t *iv, uint32_t ivLen+                         , uint8_t *aad, uint32_t aadLen+                         , uint8_t *ct, uint32_t ctLen+                         , uint8_t *pt, uint8_t *tag)+{+    aes_gcm gcm;+    aes_gcm_init(&gcm, k, iv, ivLen);+    aes_gcm_aad(&gcm, aad, aadLen);+    aes_gcm_decrypt(pt, &gcm,  ct, ctLen);+    aes_gcm_finish(tag, &gcm);+}+++/* this is a really inefficient way to GF multiply.+ * the alternative without hw accel is building small tables+ * to speed up the multiplication.+ * TODO: optimise with tables+ */+void gf_mul(block128 *a, block128 *b)+{+        uint64_t a0, a1, v0, v1;+        int i, j;++        a0 = a1 = 0;+        v0 = cpu_to_be64(a->q[0]);+        v1 = cpu_to_be64(a->q[1]);++        for (i = 0; i < 16; i++)+                for (j = 0x80; j != 0; j >>= 1) {+                        uint8_t x = b->b[i] & j;+                        a0 ^= x ? v0 : 0;+                        a1 ^= x ? v1 : 0;+                        x = (uint8_t) v1 & 1;+                        v1 = (v1 >> 1) | (v0 << 63);+                        v0 = (v0 >> 1) ^ (x ? (0xe1ULL << 56) : 0);+                }+        a->q[0] = cpu_to_be64(a0);+        a->q[1] = cpu_to_be64(a1);+}
+ cbits/aes/generic/aes_generic.c view
@@ -0,0 +1,442 @@+/*+ * Copyright (C) 2008 Vincent Hanquez <vincent@snarc.org>+ *+ * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the author nor the names of his contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ *+ * AES implementation+ */++#include <stdint.h>+#include <stdlib.h>+#include "aes_types.h"+#include "bitfn.h"++static uint8_t sbox[256] = {+	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe,+	0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4,+	0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7,+	0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3,+	0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09,+	0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3,+	0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe,+	0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,+	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92,+	0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,+	0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,+	0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,+	0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2,+	0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5,+	0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25,+	0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,+	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86,+	0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e,+	0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42,+	0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16+};++static uint8_t rsbox[256] = {+	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81,+	0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e,+	0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23,+	0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66,+	0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72,+	0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65,+	0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46,+	0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,+	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca,+	0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91,+	0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,+	0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,+	0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f,+	0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2,+	0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8,+	0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,+	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93,+	0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb,+	0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,+	0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d+};++static uint8_t Rcon[] = {+	0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,+	0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,+	0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,+	0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb,+};++#define G(a,b,c,d,e,f) { a,b,c,d,e,f }+uint8_t gmtab[256][6] =+{+	G(0x00, 0x00, 0x00, 0x00, 0x00, 0x00), G(0x02, 0x03, 0x09, 0x0b, 0x0d, 0x0e),+	G(0x04, 0x06, 0x12, 0x16, 0x1a, 0x1c), G(0x06, 0x05, 0x1b, 0x1d, 0x17, 0x12),+	G(0x08, 0x0c, 0x24, 0x2c, 0x34, 0x38), G(0x0a, 0x0f, 0x2d, 0x27, 0x39, 0x36),+	G(0x0c, 0x0a, 0x36, 0x3a, 0x2e, 0x24), G(0x0e, 0x09, 0x3f, 0x31, 0x23, 0x2a),+	G(0x10, 0x18, 0x48, 0x58, 0x68, 0x70), G(0x12, 0x1b, 0x41, 0x53, 0x65, 0x7e),+	G(0x14, 0x1e, 0x5a, 0x4e, 0x72, 0x6c), G(0x16, 0x1d, 0x53, 0x45, 0x7f, 0x62),+	G(0x18, 0x14, 0x6c, 0x74, 0x5c, 0x48), G(0x1a, 0x17, 0x65, 0x7f, 0x51, 0x46),+	G(0x1c, 0x12, 0x7e, 0x62, 0x46, 0x54), G(0x1e, 0x11, 0x77, 0x69, 0x4b, 0x5a),+	G(0x20, 0x30, 0x90, 0xb0, 0xd0, 0xe0), G(0x22, 0x33, 0x99, 0xbb, 0xdd, 0xee),+	G(0x24, 0x36, 0x82, 0xa6, 0xca, 0xfc), G(0x26, 0x35, 0x8b, 0xad, 0xc7, 0xf2),+	G(0x28, 0x3c, 0xb4, 0x9c, 0xe4, 0xd8), G(0x2a, 0x3f, 0xbd, 0x97, 0xe9, 0xd6),+	G(0x2c, 0x3a, 0xa6, 0x8a, 0xfe, 0xc4), G(0x2e, 0x39, 0xaf, 0x81, 0xf3, 0xca),+	G(0x30, 0x28, 0xd8, 0xe8, 0xb8, 0x90), G(0x32, 0x2b, 0xd1, 0xe3, 0xb5, 0x9e),+	G(0x34, 0x2e, 0xca, 0xfe, 0xa2, 0x8c), G(0x36, 0x2d, 0xc3, 0xf5, 0xaf, 0x82),+	G(0x38, 0x24, 0xfc, 0xc4, 0x8c, 0xa8), G(0x3a, 0x27, 0xf5, 0xcf, 0x81, 0xa6),+	G(0x3c, 0x22, 0xee, 0xd2, 0x96, 0xb4), G(0x3e, 0x21, 0xe7, 0xd9, 0x9b, 0xba),+	G(0x40, 0x60, 0x3b, 0x7b, 0xbb, 0xdb), G(0x42, 0x63, 0x32, 0x70, 0xb6, 0xd5),+	G(0x44, 0x66, 0x29, 0x6d, 0xa1, 0xc7), G(0x46, 0x65, 0x20, 0x66, 0xac, 0xc9),+	G(0x48, 0x6c, 0x1f, 0x57, 0x8f, 0xe3), G(0x4a, 0x6f, 0x16, 0x5c, 0x82, 0xed),+	G(0x4c, 0x6a, 0x0d, 0x41, 0x95, 0xff), G(0x4e, 0x69, 0x04, 0x4a, 0x98, 0xf1),+	G(0x50, 0x78, 0x73, 0x23, 0xd3, 0xab), G(0x52, 0x7b, 0x7a, 0x28, 0xde, 0xa5),+	G(0x54, 0x7e, 0x61, 0x35, 0xc9, 0xb7), G(0x56, 0x7d, 0x68, 0x3e, 0xc4, 0xb9),+	G(0x58, 0x74, 0x57, 0x0f, 0xe7, 0x93), G(0x5a, 0x77, 0x5e, 0x04, 0xea, 0x9d),+	G(0x5c, 0x72, 0x45, 0x19, 0xfd, 0x8f), G(0x5e, 0x71, 0x4c, 0x12, 0xf0, 0x81),+	G(0x60, 0x50, 0xab, 0xcb, 0x6b, 0x3b), G(0x62, 0x53, 0xa2, 0xc0, 0x66, 0x35),+	G(0x64, 0x56, 0xb9, 0xdd, 0x71, 0x27), G(0x66, 0x55, 0xb0, 0xd6, 0x7c, 0x29),+	G(0x68, 0x5c, 0x8f, 0xe7, 0x5f, 0x03), G(0x6a, 0x5f, 0x86, 0xec, 0x52, 0x0d),+	G(0x6c, 0x5a, 0x9d, 0xf1, 0x45, 0x1f), G(0x6e, 0x59, 0x94, 0xfa, 0x48, 0x11),+	G(0x70, 0x48, 0xe3, 0x93, 0x03, 0x4b), G(0x72, 0x4b, 0xea, 0x98, 0x0e, 0x45),+	G(0x74, 0x4e, 0xf1, 0x85, 0x19, 0x57), G(0x76, 0x4d, 0xf8, 0x8e, 0x14, 0x59),+	G(0x78, 0x44, 0xc7, 0xbf, 0x37, 0x73), G(0x7a, 0x47, 0xce, 0xb4, 0x3a, 0x7d),+	G(0x7c, 0x42, 0xd5, 0xa9, 0x2d, 0x6f), G(0x7e, 0x41, 0xdc, 0xa2, 0x20, 0x61),+	G(0x80, 0xc0, 0x76, 0xf6, 0x6d, 0xad), G(0x82, 0xc3, 0x7f, 0xfd, 0x60, 0xa3),+	G(0x84, 0xc6, 0x64, 0xe0, 0x77, 0xb1), G(0x86, 0xc5, 0x6d, 0xeb, 0x7a, 0xbf),+	G(0x88, 0xcc, 0x52, 0xda, 0x59, 0x95), G(0x8a, 0xcf, 0x5b, 0xd1, 0x54, 0x9b),+	G(0x8c, 0xca, 0x40, 0xcc, 0x43, 0x89), G(0x8e, 0xc9, 0x49, 0xc7, 0x4e, 0x87),+	G(0x90, 0xd8, 0x3e, 0xae, 0x05, 0xdd), G(0x92, 0xdb, 0x37, 0xa5, 0x08, 0xd3),+	G(0x94, 0xde, 0x2c, 0xb8, 0x1f, 0xc1), G(0x96, 0xdd, 0x25, 0xb3, 0x12, 0xcf),+	G(0x98, 0xd4, 0x1a, 0x82, 0x31, 0xe5), G(0x9a, 0xd7, 0x13, 0x89, 0x3c, 0xeb),+	G(0x9c, 0xd2, 0x08, 0x94, 0x2b, 0xf9), G(0x9e, 0xd1, 0x01, 0x9f, 0x26, 0xf7),+	G(0xa0, 0xf0, 0xe6, 0x46, 0xbd, 0x4d), G(0xa2, 0xf3, 0xef, 0x4d, 0xb0, 0x43),+	G(0xa4, 0xf6, 0xf4, 0x50, 0xa7, 0x51), G(0xa6, 0xf5, 0xfd, 0x5b, 0xaa, 0x5f),+	G(0xa8, 0xfc, 0xc2, 0x6a, 0x89, 0x75), G(0xaa, 0xff, 0xcb, 0x61, 0x84, 0x7b),+	G(0xac, 0xfa, 0xd0, 0x7c, 0x93, 0x69), G(0xae, 0xf9, 0xd9, 0x77, 0x9e, 0x67),+	G(0xb0, 0xe8, 0xae, 0x1e, 0xd5, 0x3d), G(0xb2, 0xeb, 0xa7, 0x15, 0xd8, 0x33),+	G(0xb4, 0xee, 0xbc, 0x08, 0xcf, 0x21), G(0xb6, 0xed, 0xb5, 0x03, 0xc2, 0x2f),+	G(0xb8, 0xe4, 0x8a, 0x32, 0xe1, 0x05), G(0xba, 0xe7, 0x83, 0x39, 0xec, 0x0b),+	G(0xbc, 0xe2, 0x98, 0x24, 0xfb, 0x19), G(0xbe, 0xe1, 0x91, 0x2f, 0xf6, 0x17),+	G(0xc0, 0xa0, 0x4d, 0x8d, 0xd6, 0x76), G(0xc2, 0xa3, 0x44, 0x86, 0xdb, 0x78),+	G(0xc4, 0xa6, 0x5f, 0x9b, 0xcc, 0x6a), G(0xc6, 0xa5, 0x56, 0x90, 0xc1, 0x64),+	G(0xc8, 0xac, 0x69, 0xa1, 0xe2, 0x4e), G(0xca, 0xaf, 0x60, 0xaa, 0xef, 0x40),+	G(0xcc, 0xaa, 0x7b, 0xb7, 0xf8, 0x52), G(0xce, 0xa9, 0x72, 0xbc, 0xf5, 0x5c),+	G(0xd0, 0xb8, 0x05, 0xd5, 0xbe, 0x06), G(0xd2, 0xbb, 0x0c, 0xde, 0xb3, 0x08),+	G(0xd4, 0xbe, 0x17, 0xc3, 0xa4, 0x1a), G(0xd6, 0xbd, 0x1e, 0xc8, 0xa9, 0x14),+	G(0xd8, 0xb4, 0x21, 0xf9, 0x8a, 0x3e), G(0xda, 0xb7, 0x28, 0xf2, 0x87, 0x30),+	G(0xdc, 0xb2, 0x33, 0xef, 0x90, 0x22), G(0xde, 0xb1, 0x3a, 0xe4, 0x9d, 0x2c),+	G(0xe0, 0x90, 0xdd, 0x3d, 0x06, 0x96), G(0xe2, 0x93, 0xd4, 0x36, 0x0b, 0x98),+	G(0xe4, 0x96, 0xcf, 0x2b, 0x1c, 0x8a), G(0xe6, 0x95, 0xc6, 0x20, 0x11, 0x84),+	G(0xe8, 0x9c, 0xf9, 0x11, 0x32, 0xae), G(0xea, 0x9f, 0xf0, 0x1a, 0x3f, 0xa0),+	G(0xec, 0x9a, 0xeb, 0x07, 0x28, 0xb2), G(0xee, 0x99, 0xe2, 0x0c, 0x25, 0xbc),+	G(0xf0, 0x88, 0x95, 0x65, 0x6e, 0xe6), G(0xf2, 0x8b, 0x9c, 0x6e, 0x63, 0xe8),+	G(0xf4, 0x8e, 0x87, 0x73, 0x74, 0xfa), G(0xf6, 0x8d, 0x8e, 0x78, 0x79, 0xf4),+	G(0xf8, 0x84, 0xb1, 0x49, 0x5a, 0xde), G(0xfa, 0x87, 0xb8, 0x42, 0x57, 0xd0),+	G(0xfc, 0x82, 0xa3, 0x5f, 0x40, 0xc2), G(0xfe, 0x81, 0xaa, 0x54, 0x4d, 0xcc),+	G(0x1b, 0x9b, 0xec, 0xf7, 0xda, 0x41), G(0x19, 0x98, 0xe5, 0xfc, 0xd7, 0x4f),+	G(0x1f, 0x9d, 0xfe, 0xe1, 0xc0, 0x5d), G(0x1d, 0x9e, 0xf7, 0xea, 0xcd, 0x53),+	G(0x13, 0x97, 0xc8, 0xdb, 0xee, 0x79), G(0x11, 0x94, 0xc1, 0xd0, 0xe3, 0x77),+	G(0x17, 0x91, 0xda, 0xcd, 0xf4, 0x65), G(0x15, 0x92, 0xd3, 0xc6, 0xf9, 0x6b),+	G(0x0b, 0x83, 0xa4, 0xaf, 0xb2, 0x31), G(0x09, 0x80, 0xad, 0xa4, 0xbf, 0x3f),+	G(0x0f, 0x85, 0xb6, 0xb9, 0xa8, 0x2d), G(0x0d, 0x86, 0xbf, 0xb2, 0xa5, 0x23),+	G(0x03, 0x8f, 0x80, 0x83, 0x86, 0x09), G(0x01, 0x8c, 0x89, 0x88, 0x8b, 0x07),+	G(0x07, 0x89, 0x92, 0x95, 0x9c, 0x15), G(0x05, 0x8a, 0x9b, 0x9e, 0x91, 0x1b),+	G(0x3b, 0xab, 0x7c, 0x47, 0x0a, 0xa1), G(0x39, 0xa8, 0x75, 0x4c, 0x07, 0xaf),+	G(0x3f, 0xad, 0x6e, 0x51, 0x10, 0xbd), G(0x3d, 0xae, 0x67, 0x5a, 0x1d, 0xb3),+	G(0x33, 0xa7, 0x58, 0x6b, 0x3e, 0x99), G(0x31, 0xa4, 0x51, 0x60, 0x33, 0x97),+	G(0x37, 0xa1, 0x4a, 0x7d, 0x24, 0x85), G(0x35, 0xa2, 0x43, 0x76, 0x29, 0x8b),+	G(0x2b, 0xb3, 0x34, 0x1f, 0x62, 0xd1), G(0x29, 0xb0, 0x3d, 0x14, 0x6f, 0xdf),+	G(0x2f, 0xb5, 0x26, 0x09, 0x78, 0xcd), G(0x2d, 0xb6, 0x2f, 0x02, 0x75, 0xc3),+	G(0x23, 0xbf, 0x10, 0x33, 0x56, 0xe9), G(0x21, 0xbc, 0x19, 0x38, 0x5b, 0xe7),+	G(0x27, 0xb9, 0x02, 0x25, 0x4c, 0xf5), G(0x25, 0xba, 0x0b, 0x2e, 0x41, 0xfb),+	G(0x5b, 0xfb, 0xd7, 0x8c, 0x61, 0x9a), G(0x59, 0xf8, 0xde, 0x87, 0x6c, 0x94),+	G(0x5f, 0xfd, 0xc5, 0x9a, 0x7b, 0x86), G(0x5d, 0xfe, 0xcc, 0x91, 0x76, 0x88),+	G(0x53, 0xf7, 0xf3, 0xa0, 0x55, 0xa2), G(0x51, 0xf4, 0xfa, 0xab, 0x58, 0xac),+	G(0x57, 0xf1, 0xe1, 0xb6, 0x4f, 0xbe), G(0x55, 0xf2, 0xe8, 0xbd, 0x42, 0xb0),+	G(0x4b, 0xe3, 0x9f, 0xd4, 0x09, 0xea), G(0x49, 0xe0, 0x96, 0xdf, 0x04, 0xe4),+	G(0x4f, 0xe5, 0x8d, 0xc2, 0x13, 0xf6), G(0x4d, 0xe6, 0x84, 0xc9, 0x1e, 0xf8),+	G(0x43, 0xef, 0xbb, 0xf8, 0x3d, 0xd2), G(0x41, 0xec, 0xb2, 0xf3, 0x30, 0xdc),+	G(0x47, 0xe9, 0xa9, 0xee, 0x27, 0xce), G(0x45, 0xea, 0xa0, 0xe5, 0x2a, 0xc0),+	G(0x7b, 0xcb, 0x47, 0x3c, 0xb1, 0x7a), G(0x79, 0xc8, 0x4e, 0x37, 0xbc, 0x74),+	G(0x7f, 0xcd, 0x55, 0x2a, 0xab, 0x66), G(0x7d, 0xce, 0x5c, 0x21, 0xa6, 0x68),+	G(0x73, 0xc7, 0x63, 0x10, 0x85, 0x42), G(0x71, 0xc4, 0x6a, 0x1b, 0x88, 0x4c),+	G(0x77, 0xc1, 0x71, 0x06, 0x9f, 0x5e), G(0x75, 0xc2, 0x78, 0x0d, 0x92, 0x50),+	G(0x6b, 0xd3, 0x0f, 0x64, 0xd9, 0x0a), G(0x69, 0xd0, 0x06, 0x6f, 0xd4, 0x04),+	G(0x6f, 0xd5, 0x1d, 0x72, 0xc3, 0x16), G(0x6d, 0xd6, 0x14, 0x79, 0xce, 0x18),+	G(0x63, 0xdf, 0x2b, 0x48, 0xed, 0x32), G(0x61, 0xdc, 0x22, 0x43, 0xe0, 0x3c),+	G(0x67, 0xd9, 0x39, 0x5e, 0xf7, 0x2e), G(0x65, 0xda, 0x30, 0x55, 0xfa, 0x20),+	G(0x9b, 0x5b, 0x9a, 0x01, 0xb7, 0xec), G(0x99, 0x58, 0x93, 0x0a, 0xba, 0xe2),+	G(0x9f, 0x5d, 0x88, 0x17, 0xad, 0xf0), G(0x9d, 0x5e, 0x81, 0x1c, 0xa0, 0xfe),+	G(0x93, 0x57, 0xbe, 0x2d, 0x83, 0xd4), G(0x91, 0x54, 0xb7, 0x26, 0x8e, 0xda),+	G(0x97, 0x51, 0xac, 0x3b, 0x99, 0xc8), G(0x95, 0x52, 0xa5, 0x30, 0x94, 0xc6),+	G(0x8b, 0x43, 0xd2, 0x59, 0xdf, 0x9c), G(0x89, 0x40, 0xdb, 0x52, 0xd2, 0x92),+	G(0x8f, 0x45, 0xc0, 0x4f, 0xc5, 0x80), G(0x8d, 0x46, 0xc9, 0x44, 0xc8, 0x8e),+	G(0x83, 0x4f, 0xf6, 0x75, 0xeb, 0xa4), G(0x81, 0x4c, 0xff, 0x7e, 0xe6, 0xaa),+	G(0x87, 0x49, 0xe4, 0x63, 0xf1, 0xb8), G(0x85, 0x4a, 0xed, 0x68, 0xfc, 0xb6),+	G(0xbb, 0x6b, 0x0a, 0xb1, 0x67, 0x0c), G(0xb9, 0x68, 0x03, 0xba, 0x6a, 0x02),+	G(0xbf, 0x6d, 0x18, 0xa7, 0x7d, 0x10), G(0xbd, 0x6e, 0x11, 0xac, 0x70, 0x1e),+	G(0xb3, 0x67, 0x2e, 0x9d, 0x53, 0x34), G(0xb1, 0x64, 0x27, 0x96, 0x5e, 0x3a),+	G(0xb7, 0x61, 0x3c, 0x8b, 0x49, 0x28), G(0xb5, 0x62, 0x35, 0x80, 0x44, 0x26),+	G(0xab, 0x73, 0x42, 0xe9, 0x0f, 0x7c), G(0xa9, 0x70, 0x4b, 0xe2, 0x02, 0x72),+	G(0xaf, 0x75, 0x50, 0xff, 0x15, 0x60), G(0xad, 0x76, 0x59, 0xf4, 0x18, 0x6e),+	G(0xa3, 0x7f, 0x66, 0xc5, 0x3b, 0x44), G(0xa1, 0x7c, 0x6f, 0xce, 0x36, 0x4a),+	G(0xa7, 0x79, 0x74, 0xd3, 0x21, 0x58), G(0xa5, 0x7a, 0x7d, 0xd8, 0x2c, 0x56),+	G(0xdb, 0x3b, 0xa1, 0x7a, 0x0c, 0x37), G(0xd9, 0x38, 0xa8, 0x71, 0x01, 0x39),+	G(0xdf, 0x3d, 0xb3, 0x6c, 0x16, 0x2b), G(0xdd, 0x3e, 0xba, 0x67, 0x1b, 0x25),+	G(0xd3, 0x37, 0x85, 0x56, 0x38, 0x0f), G(0xd1, 0x34, 0x8c, 0x5d, 0x35, 0x01),+	G(0xd7, 0x31, 0x97, 0x40, 0x22, 0x13), G(0xd5, 0x32, 0x9e, 0x4b, 0x2f, 0x1d),+	G(0xcb, 0x23, 0xe9, 0x22, 0x64, 0x47), G(0xc9, 0x20, 0xe0, 0x29, 0x69, 0x49),+	G(0xcf, 0x25, 0xfb, 0x34, 0x7e, 0x5b), G(0xcd, 0x26, 0xf2, 0x3f, 0x73, 0x55),+	G(0xc3, 0x2f, 0xcd, 0x0e, 0x50, 0x7f), G(0xc1, 0x2c, 0xc4, 0x05, 0x5d, 0x71),+	G(0xc7, 0x29, 0xdf, 0x18, 0x4a, 0x63), G(0xc5, 0x2a, 0xd6, 0x13, 0x47, 0x6d),+	G(0xfb, 0x0b, 0x31, 0xca, 0xdc, 0xd7), G(0xf9, 0x08, 0x38, 0xc1, 0xd1, 0xd9),+	G(0xff, 0x0d, 0x23, 0xdc, 0xc6, 0xcb), G(0xfd, 0x0e, 0x2a, 0xd7, 0xcb, 0xc5),+	G(0xf3, 0x07, 0x15, 0xe6, 0xe8, 0xef), G(0xf1, 0x04, 0x1c, 0xed, 0xe5, 0xe1),+	G(0xf7, 0x01, 0x07, 0xf0, 0xf2, 0xf3), G(0xf5, 0x02, 0x0e, 0xfb, 0xff, 0xfd),+	G(0xeb, 0x13, 0x79, 0x92, 0xb4, 0xa7), G(0xe9, 0x10, 0x70, 0x99, 0xb9, 0xa9),+	G(0xef, 0x15, 0x6b, 0x84, 0xae, 0xbb), G(0xed, 0x16, 0x62, 0x8f, 0xa3, 0xb5),+	G(0xe3, 0x1f, 0x5d, 0xbe, 0x80, 0x9f), G(0xe1, 0x1c, 0x54, 0xb5, 0x8d, 0x91),+	G(0xe7, 0x19, 0x4f, 0xa8, 0x9a, 0x83), G(0xe5, 0x1a, 0x46, 0xa3, 0x97, 0x8d),+};+#undef G++static void expand_key(uint8_t *expandedKey, const uint8_t *key, int size, size_t expandedKeySize)+{+	int csz;+	int i;+	uint8_t t[4] = { 0 };++	for (i = 0; i < size; i++)+		expandedKey[i] = key[i];+	csz = size;++	i = 1;+	while (csz < expandedKeySize) {+		t[0] = expandedKey[(csz - 4) + 0];+		t[1] = expandedKey[(csz - 4) + 1];+		t[2] = expandedKey[(csz - 4) + 2];+		t[3] = expandedKey[(csz - 4) + 3];++		if (csz % size == 0) {+			uint8_t tmp;++			tmp = t[0];+			t[0] = sbox[t[1]] ^ Rcon[i++ % sizeof(Rcon)];+			t[1] = sbox[t[2]];+			t[2] = sbox[t[3]];+			t[3] = sbox[tmp];+		}++		if (size == 32 && ((csz % size) == 16)) {+			t[0] = sbox[t[0]];+			t[1] = sbox[t[1]];+			t[2] = sbox[t[2]];+			t[3] = sbox[t[3]];+		}++		expandedKey[csz] = expandedKey[csz - size] ^ t[0]; csz++;+		expandedKey[csz] = expandedKey[csz - size] ^ t[1]; csz++;+		expandedKey[csz] = expandedKey[csz - size] ^ t[2]; csz++;+		expandedKey[csz] = expandedKey[csz - size] ^ t[3]; csz++;+	}+}++static void shift_rows(uint8_t *state)+{+	uint32_t *s32;+	int i;++	for (i = 0; i < 16; i++)+		state[i] = sbox[state[i]];+	s32 = (uint32_t *) state;+	s32[1] = rol32_be(s32[1], 8);+	s32[2] = rol32_be(s32[2], 16);+	s32[3] = rol32_be(s32[3], 24);+}++static void add_round_key(uint8_t *state, uint8_t *rk)+{+	uint32_t *s32, *r32;++	s32 = (uint32_t *) state;+	r32 = (uint32_t *) rk;+	s32[0] ^= r32[0];+	s32[1] ^= r32[1];+	s32[2] ^= r32[2];+	s32[3] ^= r32[3];+}++#define gm1(a) (a)+#define gm2(a) gmtab[a][0]+#define gm3(a) gmtab[a][1]+#define gm9(a) gmtab[a][2]+#define gm11(a) gmtab[a][3]+#define gm13(a) gmtab[a][4]+#define gm14(a) gmtab[a][5]++static void mix_columns(uint8_t *state)+{+	int i;+	uint8_t cpy[4];++	for (i = 0; i < 4; i++) {+		cpy[0] = state[0 * 4 + i];+		cpy[1] = state[1 * 4 + i];+		cpy[2] = state[2 * 4 + i];+		cpy[3] = state[3 * 4 + i];+		state[i] = gm2(cpy[0]) ^ gm1(cpy[3]) ^ gm1(cpy[2]) ^ gm3(cpy[1]);+		state[4+i] = gm2(cpy[1]) ^ gm1(cpy[0]) ^ gm1(cpy[3]) ^ gm3(cpy[2]);+		state[8+i] = gm2(cpy[2]) ^ gm1(cpy[1]) ^ gm1(cpy[0]) ^ gm3(cpy[3]);+		state[12+i] = gm2(cpy[3]) ^ gm1(cpy[2]) ^ gm1(cpy[1]) ^ gm3(cpy[0]);+	}+}++static void create_round_key(const uint8_t *expandedKey, uint8_t *rk)+{+	int i,j;+	for (i = 0; i < 4; i++)+		for (j = 0; j < 4; j++)+			rk[i + j * 4] = expandedKey[i * 4 + j];+}++static void aes_main(const aes_key *key, uint8_t *state)+{+	int i = 0;+	uint8_t rk[16];++	create_round_key(key->data, rk);+	add_round_key(state, rk);++	for (i = 1; i < key->nbr; i++) {+		create_round_key(key->data + 16 * i, rk);+		shift_rows(state);+		mix_columns(state);+		add_round_key(state, rk);+	}++	create_round_key(key->data + 16 * key->nbr, rk);+	shift_rows(state);+	add_round_key(state, rk);+}++static void shift_rows_inv(uint8_t *state)+{+	uint32_t *s32;+	int i;++	s32 = (uint32_t *) state;+	s32[1] = ror32_be(s32[1], 8);+	s32[2] = ror32_be(s32[2], 16);+	s32[3] = ror32_be(s32[3], 24);+	for (i = 0; i < 16; i++)+		state[i] = rsbox[state[i]];+}++static void mix_columns_inv(uint8_t *state)+{+	int i;+	uint8_t cpy[4];++	for (i = 0; i < 4; i++) {+		cpy[0] = state[0 * 4 + i];+		cpy[1] = state[1 * 4 + i];+		cpy[2] = state[2 * 4 + i];+		cpy[3] = state[3 * 4 + i];+		state[i] = gm14(cpy[0]) ^ gm9(cpy[3]) ^ gm13(cpy[2]) ^ gm11(cpy[1]);+		state[4+i] = gm14(cpy[1]) ^ gm9(cpy[0]) ^ gm13(cpy[3]) ^ gm11(cpy[2]);+		state[8+i] = gm14(cpy[2]) ^ gm9(cpy[1]) ^ gm13(cpy[0]) ^ gm11(cpy[3]);+		state[12+i] = gm14(cpy[3]) ^ gm9(cpy[2]) ^ gm13(cpy[1]) ^ gm11(cpy[0]);+	}+}++static void aes_main_inv(const aes_key *key, uint8_t *state)+{+	int i = 0;+	uint8_t rk[16];++	create_round_key(key->data + 16 * key->nbr, rk);+	add_round_key(state, rk);++	for (i = key->nbr - 1; i > 0; i--) {+		create_round_key(key->data + 16 * i, rk);+		shift_rows_inv(state);+		add_round_key(state, rk);+		mix_columns_inv(state);+	}++	create_round_key(key->data, rk);+	shift_rows_inv(state);+	add_round_key(state, rk);+}++/* Set the block values, for the block:+ * a0,0 a0,1 a0,2 a0,3+ * a1,0 a1,1 a1,2 a1,3 -> a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3+ * a2,0 a2,1 a2,2 a2,3+ * a3,0 a3,1 a3,2 a3,3+ */+#define swap_block(t, f) \+	t[0] = f[0]; t[4] = f[1]; t[8] = f[2]; t[12] = f[3]; \+	t[1] = f[4]; t[5] = f[5]; t[9] = f[6]; t[13] = f[7]; \+	t[2] = f[8]; t[6] = f[9]; t[10] = f[10]; t[14] = f[11]; \+	t[3] = f[12]; t[7] = f[13]; t[11] = f[14]; t[15] = f[15]++void aes_generic_encrypt_block(aes_block *output, const aes_key *key, const aes_block *input)+{+	uint8_t block[16];+	uint8_t *iptr, *optr;++	iptr = (uint8_t *) input;+	optr = (uint8_t *) output;+	swap_block(block, iptr);+	aes_main(key, block);+	swap_block(optr, block);+}++void aes_generic_decrypt_block(aes_block *output, const aes_key *key, const aes_block *input)+{+	uint8_t block[16];+	uint8_t *iptr, *optr;++	iptr = (uint8_t *) input;+	optr = (uint8_t *) output;+	swap_block(block, iptr);+	aes_main_inv(key, block);+	swap_block(optr, block);+}++void aes_generic_init(aes_key *key, const uint8_t *origkey, uint8_t size)+{+	int esz;++	switch (size) {+	case 16: key->nbr = 10; esz = 176; break;+	case 24: key->nbr = 12; esz = 208; break;+	case 32: key->nbr = 14; esz = 240; break;+	default: return;+	}+	expand_key(key->data, origkey, size, esz);+	return;+}
+ cbits/aes/ni/aes_x86ni.c view
@@ -0,0 +1,271 @@+/*+ * Copyright (c) 2012 Vincent Hanquez <vincent@snarc.org>+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the author nor the names of his contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <wmmintrin.h>+#include <tmmintrin.h>+#include "aes.h"+#include "aes_x86ni.h"+// #include "cpu.h"++#if (defined(__i386__) || defined(__x86_64__))+#define ALIGN_UP(addr, size) (((addr) + ((size) - 1)) & (~((size) - 1)))+#define ALIGNMENT(n) __attribute__((aligned(n)))++static __m128i aes_128_key_expansion(__m128i key, __m128i keygened)+{+	keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3,3,3,3));+	key = _mm_xor_si128(key, _mm_slli_si128(key, 4));+	key = _mm_xor_si128(key, _mm_slli_si128(key, 4));+	key = _mm_xor_si128(key, _mm_slli_si128(key, 4));+	return _mm_xor_si128(key, keygened);+}++static void aes_generate_key128(aes_key *key, const uint8_t *ikey)+{+	__m128i k[20];+	uint64_t *out = (uint64_t *) key->data;+	int i;++	k[0] = _mm_loadu_si128((const __m128i*) ikey);++#define AES_128_key_exp(K, RCON) aes_128_key_expansion(K, _mm_aeskeygenassist_si128(K, RCON))+	k[1]  = AES_128_key_exp(k[0], 0x01);+	k[2]  = AES_128_key_exp(k[1], 0x02);+	k[3]  = AES_128_key_exp(k[2], 0x04);+	k[4]  = AES_128_key_exp(k[3], 0x08);+	k[5]  = AES_128_key_exp(k[4], 0x10);+	k[6]  = AES_128_key_exp(k[5], 0x20);+	k[7]  = AES_128_key_exp(k[6], 0x40);+	k[8]  = AES_128_key_exp(k[7], 0x80);+	k[9]  = AES_128_key_exp(k[8], 0x1B);+	k[10] = AES_128_key_exp(k[9], 0x36);++	/* generate decryption keys in reverse order.+	 * k[10] is shared by last encryption and first decryption rounds+	 * k[20] is shared by first encryption round (and is the original user key) */+	k[11] = _mm_aesimc_si128(k[9]);+	k[12] = _mm_aesimc_si128(k[8]);+	k[13] = _mm_aesimc_si128(k[7]);+	k[14] = _mm_aesimc_si128(k[6]);+	k[15] = _mm_aesimc_si128(k[5]);+	k[16] = _mm_aesimc_si128(k[4]);+	k[17] = _mm_aesimc_si128(k[3]);+	k[18] = _mm_aesimc_si128(k[2]);+	k[19] = _mm_aesimc_si128(k[1]);++	for (i = 0; i < 20; i++)+		_mm_storeu_si128(((__m128i *) out) + i, k[i]);+}++void aes_ni_init(aes_key *key, const uint8_t *origkey, uint8_t size)+{+	switch (size) {+	case 16: aes_generate_key128(key, origkey); break;+	default: break;+	}+}+++#define PRELOAD_ENC_KEYS(k) \+	__m128i K0  = _mm_loadu_si128(((__m128i *) k)+0); \+	__m128i K1  = _mm_loadu_si128(((__m128i *) k)+1); \+	__m128i K2  = _mm_loadu_si128(((__m128i *) k)+2); \+	__m128i K3  = _mm_loadu_si128(((__m128i *) k)+3); \+	__m128i K4  = _mm_loadu_si128(((__m128i *) k)+4); \+	__m128i K5  = _mm_loadu_si128(((__m128i *) k)+5); \+	__m128i K6  = _mm_loadu_si128(((__m128i *) k)+6); \+	__m128i K7  = _mm_loadu_si128(((__m128i *) k)+7); \+	__m128i K8  = _mm_loadu_si128(((__m128i *) k)+8); \+	__m128i K9  = _mm_loadu_si128(((__m128i *) k)+9); \+	__m128i K10 = _mm_loadu_si128(((__m128i *) k)+10);++#define DO_ENC_BLOCK(m) \+	m = _mm_xor_si128(m, K0); \+	m = _mm_aesenc_si128(m, K1); \+	m = _mm_aesenc_si128(m, K2); \+	m = _mm_aesenc_si128(m, K3); \+	m = _mm_aesenc_si128(m, K4); \+	m = _mm_aesenc_si128(m, K5); \+	m = _mm_aesenc_si128(m, K6); \+	m = _mm_aesenc_si128(m, K7); \+	m = _mm_aesenc_si128(m, K8); \+	m = _mm_aesenc_si128(m, K9); \+	m = _mm_aesenclast_si128(m, K10);++#define PRELOAD_DEC_KEYS(k) \+	__m128i K0  = _mm_loadu_si128(((__m128i *) k)+10+0); \+	__m128i K1  = _mm_loadu_si128(((__m128i *) k)+10+1); \+	__m128i K2  = _mm_loadu_si128(((__m128i *) k)+10+2); \+	__m128i K3  = _mm_loadu_si128(((__m128i *) k)+10+3); \+	__m128i K4  = _mm_loadu_si128(((__m128i *) k)+10+4); \+	__m128i K5  = _mm_loadu_si128(((__m128i *) k)+10+5); \+	__m128i K6  = _mm_loadu_si128(((__m128i *) k)+10+6); \+	__m128i K7  = _mm_loadu_si128(((__m128i *) k)+10+7); \+	__m128i K8  = _mm_loadu_si128(((__m128i *) k)+10+8); \+	__m128i K9  = _mm_loadu_si128(((__m128i *) k)+10+9); \+	__m128i K10 = _mm_loadu_si128(((__m128i *) k)+0);++#define DO_DEC_BLOCK(m) \+	m = _mm_xor_si128(m, K0); \+	m = _mm_aesdec_si128(m, K1); \+	m = _mm_aesdec_si128(m, K2); \+	m = _mm_aesdec_si128(m, K3); \+	m = _mm_aesdec_si128(m, K4); \+	m = _mm_aesdec_si128(m, K5); \+	m = _mm_aesdec_si128(m, K6); \+	m = _mm_aesdec_si128(m, K7); \+	m = _mm_aesdec_si128(m, K8); \+	m = _mm_aesdec_si128(m, K9); \+	m = _mm_aesdeclast_si128(m, K10);++void aes_ni_encrypt_ecb(uint8_t *out, aes_key *key, const uint8_t *in, uint32_t blocks)+{+	__m128i *k = (__m128i *) key->data;++	PRELOAD_ENC_KEYS(k);++	while (blocks-- > 0) {+		__m128i m = _mm_loadu_si128((__m128i *) in);++		DO_ENC_BLOCK(m);++		_mm_storeu_si128((__m128i *) out, m);+		in += 16;+		out += 16;+	}+}++void aes_ni_decrypt_ecb(uint8_t *out, aes_key *key, const uint8_t *in, uint32_t blocks)+{+	__m128i *k = (__m128i *) key->data;++	PRELOAD_DEC_KEYS(k);++	while (blocks-- > 0) {+		__m128i m = _mm_loadu_si128((__m128i *) in);++		DO_DEC_BLOCK(m);++		_mm_storeu_si128((__m128i *) out, m);+		in += 16;+		out += 16;+	}+}++void aes_ni_encrypt_cbc(uint8_t *out, aes_key *key, uint8_t *_iv, uint8_t *in, uint32_t blocks)+{+	__m128i *k = (__m128i *) key->data;+	__m128i iv = _mm_loadu_si128((__m128i *) _iv);++	PRELOAD_ENC_KEYS(k);++	while (blocks-- > 0) {+		__m128i m = _mm_loadu_si128((__m128i *) in);+		m = _mm_xor_si128(m, iv);++		DO_ENC_BLOCK(m);++		_mm_storeu_si128((__m128i *) out, m);+		iv = m;++		in += 16;+		out += 16;+	}+}++void aes_ni_decrypt_cbc(uint8_t *out, aes_key *key, uint8_t *_iv, uint8_t *in, uint32_t blocks)+{+	__m128i *k = (__m128i *) key->data;+	__m128i iv = _mm_loadu_si128((__m128i *) _iv);++	PRELOAD_DEC_KEYS(k);++	while (blocks-- > 0) {+		__m128i m = _mm_loadu_si128((__m128i *) in);+		__m128i ivnext = m;++		DO_DEC_BLOCK(m);+		m = _mm_xor_si128(m, iv);++		_mm_storeu_si128((__m128i *) out, m);+		iv = ivnext;++		in += 16;+		out += 16;+	}+}++/* TO OPTIMISE: use pcmulqdq... or some faster code.+ * this is the lamest way of doing it, but i'm out of time.+ * this is basically a copy of gf_mulx in gf.c */+static __m128i gfmulx(__m128i v)+{+	uint64_t v_[2] ALIGNMENT(16);+	const uint64_t gf_mask = 0x8000000000000000;++	_mm_store_si128((__m128i *) v_, v);+	uint64_t r = ((v_[1] & gf_mask) ? 0x87 : 0);+	v_[1] = (v_[1] << 1) | (v_[0] & gf_mask ? 1 : 0);+	v_[0] = (v_[0] << 1) ^ r;+	v = _mm_load_si128((__m128i *) v_);+	return v;+}++void aes_ni_encrypt_xts(uint8_t *out, aes_key *key1, aes_key *key2,+                        uint8_t *_tweak, uint32_t spoint, uint8_t *in, uint32_t blocks)+{+	__m128i tweak = _mm_loadu_si128((__m128i *) _tweak);++	do {+		__m128i *k2 = (__m128i *) key2->data;+		PRELOAD_ENC_KEYS(k2);+		DO_ENC_BLOCK(tweak);++		while (spoint-- > 0)+			tweak = gfmulx(tweak);+	} while (0) ;++	do {+		__m128i *k1 = (__m128i *) key1->data;+		PRELOAD_ENC_KEYS(k1);++		for ( ; blocks-- > 0; in += 16, out += 16, tweak = gfmulx(tweak)) {+			__m128i m = _mm_loadu_si128((__m128i *) in);++			m = _mm_xor_si128(m, tweak);+			DO_ENC_BLOCK(m);+			m = _mm_xor_si128(m, tweak);++			_mm_storeu_si128((__m128i *) out, m);+		}+	} while (0);+}++#endif /* x86 */
+ cbits/include/aes.h view
@@ -0,0 +1,24 @@+#ifndef AES_AES_H+#define AES_AES_H++#include <stdint.h>+#include "aes_types.h"++typedef aes_key AESKey;+AESKey *allocate_key128();+void generate_key128(AESKey *k, const uint8_t *bytes);+void free_key128(AESKey *k);+void encrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr);+void decrypt_ecb(const AESKey *k, uint8_t *dst, const uint8_t *src, const uint32_t nr);+void aes_gcm_full_encrypt( const AESKey *k+                         , uint8_t *iv, uint32_t ivLen+                         , uint8_t *aad, uint32_t aadLen+                         , uint8_t *pt, uint32_t ptLen+                         , uint8_t *ct, uint8_t *tag);+void aes_gcm_full_decrypt( const AESKey *k+                         , uint8_t *iv, uint32_t ivLen+                         , uint8_t *aad, uint32_t aadLen+                         , uint8_t *ct, uint32_t ctLen+                         , uint8_t *pt, uint8_t *tag);++#endif
+ cbits/include/aes_generic.h view
@@ -0,0 +1,36 @@+/*+ * Copyright (c) 2012 Vincent Hanquez <vincent@snarc.org>+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the author nor the names of his contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */+#include "aes_types.h"+#include "block128.h"+#include <stdint.h>++void aes_generic_encrypt_block(aes_block *output, const aes_key *key, const aes_block *input);+void aes_generic_decrypt_block(aes_block *output, const aes_key *key, const aes_block *input);+void aes_generic_init(aes_key *key, const uint8_t *origkey, uint8_t size);
+ cbits/include/aes_types.h view
@@ -0,0 +1,25 @@+#ifndef AES_TYPES_H+#define AES_TYPES_H+#include <stdint.h>+#include "block128.h"++typedef block128 aes_block;++typedef struct {+    uint8_t nbr;+    uint8_t _padding[7];+    uint8_t data[16*14*2];+} aes_key;++/* size = 4*16+2*8+aes_key=456 = 536 */+typedef struct {+    aes_block tag;+    aes_block h;+    aes_block iv;+    aes_block civ;+    uint64_t length_aad;+    uint64_t length_input;+    aes_key key;+} aes_gcm;++#endif
+ cbits/include/aes_x86ni.h view
@@ -0,0 +1,53 @@+/*+ * Copyright (c) 2012 Vincent Hanquez <vincent@snarc.org>+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the author nor the names of his contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#ifndef AES_X86NI_H+#define AES_X86NI_H++#if defined(__i386__) || defined(__x86_64__)++#include <wmmintrin.h>+#include <tmmintrin.h>+#include "aes_types.h"+#include "block128.h"++void aes_ni_init(aes_key *key, const uint8_t *origkey, uint8_t size);+void aes_ni_encrypt_ecb(uint8_t *out, aes_key *key, const uint8_t *in, uint32_t blocks);+void aes_ni_decrypt_ecb(uint8_t *out, aes_key *key, const uint8_t *in, uint32_t blocks);+void aes_ni_encrypt_cbc(uint8_t *out, aes_key *key, uint8_t *_iv, uint8_t *in, uint32_t blocks);+void aes_ni_decrypt_cbc(uint8_t *out, aes_key *key, uint8_t *_iv, uint8_t *in, uint32_t blocks);+void aes_ni_encrypt_xts(uint8_t *out, aes_key *key1, aes_key *key2,+                        uint8_t *_tweak, uint32_t spoint, uint8_t *in, uint32_t blocks);++void gf_mul_x86ni(block128 *res, block128 *a_, block128 *b_);++#endif++#endif
+ cbits/include/bitfn.h view
@@ -0,0 +1,232 @@+/*+ * Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef BITFN_H+#define BITFN_H+#include <stdint.h>++#ifndef NO_INLINE_ASM+/**********************************************************/+# if (defined(__i386__))+#  define ARCH_HAS_SWAP32+static inline uint32_t bitfn_swap32(uint32_t a)+{+	asm ("bswap %0" : "=r" (a) : "0" (a));+	return a;+}+/**********************************************************/+# elif (defined(__arm__))+#  define ARCH_HAS_SWAP32+static inline uint32_t bitfn_swap32(uint32_t a)+{+	uint32_t tmp = a;+	asm volatile ("eor %1, %0, %0, ror #16\n"+	              "bic %1, %1, #0xff0000\n"+	              "mov %0, %0, ror #8\n"+	              "eor %0, %0, %1, lsr #8\n"+	             : "=r" (a), "=r" (tmp) : "0" (a), "1" (tmp));+	return a;+}+/**********************************************************/+# elif defined(__x86_64__)+#  define ARCH_HAS_SWAP32+#  define ARCH_HAS_SWAP64+static inline uint32_t bitfn_swap32(uint32_t a)+{+	asm ("bswap %0" : "=r" (a) : "0" (a));+	return a;+}++static inline uint64_t bitfn_swap64(uint64_t a)+{+	asm ("bswap %0" : "=r" (a) : "0" (a));+	return a;+}++# endif+#endif /* NO_INLINE_ASM */+/**********************************************************/++#ifndef ARCH_HAS_ROL32+static inline uint32_t rol32(uint32_t word, uint32_t shift)+{+	return (word << shift) | (word >> (32 - shift));+}+#endif++#ifndef ARCH_HAS_ROR32+static inline uint32_t ror32(uint32_t word, uint32_t shift)+{+	return (word >> shift) | (word << (32 - shift));+}+#endif++#ifndef ARCH_HAS_ROL64+static inline uint64_t rol64(uint64_t word, uint32_t shift)+{+	return (word << shift) | (word >> (64 - shift));+}+#endif++#ifndef ARCH_HAS_ROR64+static inline uint64_t ror64(uint64_t word, uint32_t shift)+{+	return (word >> shift) | (word << (64 - shift));+}+#endif++#ifndef ARCH_HAS_SWAP32+static inline uint32_t bitfn_swap32(uint32_t a)+{+	return (a << 24) | ((a & 0xff00) << 8) | ((a >> 8) & 0xff00) | (a >> 24);+}+#endif++#ifndef ARCH_HAS_ARRAY_SWAP32+static inline void array_swap32(uint32_t *d, uint32_t *s, uint32_t nb)+{+	while (nb--)+		*d++ = bitfn_swap32(*s++);+}+#endif++#ifndef ARCH_HAS_SWAP64+static inline uint64_t bitfn_swap64(uint64_t a)+{+	return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) |+	       (((uint64_t) bitfn_swap32((uint32_t) a)) << 32);+}+#endif++#ifndef ARCH_HAS_ARRAY_SWAP64+static inline void array_swap64(uint64_t *d, uint64_t *s, uint32_t nb)+{+	while (nb--)+		*d++ = bitfn_swap64(*s++);+}+#endif++#ifndef ARCH_HAS_MEMORY_ZERO+static inline void memory_zero(void *ptr, uint32_t len)+{+	uint32_t *ptr32 = ptr;+	uint8_t *ptr8;+	int i;++	for (i = 0; i < len / 4; i++)+		*ptr32++ = 0;+	if (len % 4) {+		ptr8 = (uint8_t *) ptr32;+		for (i = len % 4; i >= 0; i--)+			ptr8[i] = 0;+	}+}+#endif++#ifndef ARCH_HAS_ARRAY_COPY32+static inline void array_copy32(uint32_t *d, uint32_t *s, uint32_t nb)+{+	while (nb--) *d++ = *s++;+}+#endif++#ifndef ARCH_HAS_ARRAY_COPY64+static inline void array_copy64(uint64_t *d, uint64_t *s, uint32_t nb)+{+	while (nb--) *d++ = *s++;+}+#endif++#ifdef __MINGW32__+  # define LITTLE_ENDIAN 1234+  # define BYTE_ORDER    LITTLE_ENDIAN+#elif defined(__FreeBSD__) || defined(__DragonFly__)+  # include <sys/endian.h>+#elif defined(__OpenBSD__) || defined(__SVR4)+  # include <sys/types.h>+#elif defined(__APPLE__)+  # include <machine/endian.h>+#elif defined( BSD ) && ( BSD >= 199103 )+  # include <machine/endian.h>+#else+  # include <endian.h>+#endif+/* big endian to cpu */+#if LITTLE_ENDIAN == BYTE_ORDER++# define be32_to_cpu(a) bitfn_swap32(a)+# define cpu_to_be32(a) bitfn_swap32(a)+# define le32_to_cpu(a) (a)+# define cpu_to_le32(a) (a)+# define be64_to_cpu(a) bitfn_swap64(a)+# define cpu_to_be64(a) bitfn_swap64(a)+# define le64_to_cpu(a) (a)+# define cpu_to_le64(a) (a)++# define cpu_to_le32_array(d, s, l) array_copy32(d, s, l)+# define le32_to_cpu_array(d, s, l) array_copy32(d, s, l)+# define cpu_to_be32_array(d, s, l) array_swap32(d, s, l)+# define be32_to_cpu_array(d, s, l) array_swap32(d, s, l)++# define cpu_to_le64_array(d, s, l) array_copy64(d, s, l)+# define le64_to_cpu_array(d, s, l) array_copy64(d, s, l)+# define cpu_to_be64_array(d, s, l) array_swap64(d, s, l)+# define be64_to_cpu_array(d, s, l) array_swap64(d, s, l)++# define ror32_be(a, s) rol32(a, s)+# define rol32_be(a, s) ror32(a, s)++# define ARCH_IS_LITTLE_ENDIAN++#elif BIG_ENDIAN == BYTE_ORDER++# define be32_to_cpu(a) (a)+# define cpu_to_be32(a) (a)+# define be64_to_cpu(a) (a)+# define cpu_to_be64(a) (a)+# define le64_to_cpu(a) bitfn_swap64(a)+# define cpu_to_le64(a) bitfn_swap64(a)+# define le32_to_cpu(a) bitfn_swap32(a)+# define cpu_to_le32(a) bitfn_swap32(a)++# define cpu_to_le32_array(d, s, l) array_swap32(d, s, l)+# define le32_to_cpu_array(d, s, l) array_swap32(d, s, l)+# define cpu_to_be32_array(d, s, l) array_copy32(d, s, l)+# define be32_to_cpu_array(d, s, l) array_copy32(d, s, l)++# define cpu_to_le64_array(d, s, l) array_swap64(d, s, l)+# define le64_to_cpu_array(d, s, l) array_swap64(d, s, l)+# define cpu_to_be64_array(d, s, l) array_copy64(d, s, l)+# define be64_to_cpu_array(d, s, l) array_copy64(d, s, l)++# define ror32_be(a, s) ror32(a, s)+# define rol32_be(a, s) rol32(a, s)++# define ARCH_IS_BIG_ENDIAN++#else+# error "endian not supported"+#endif++#endif /* !BITFN_H */
+ cbits/include/block128.h view
@@ -0,0 +1,87 @@+/*+ * Copyright (c) 2012 Vincent Hanquez <vincent@snarc.org>+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the author nor the names of his contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#ifndef BLOCK128_H+#define BLOCK128_H++#include "bitfn.h"++typedef union {+       uint64_t q[2];+       uint32_t d[4];+       uint16_t w[8];+       uint8_t  b[16];+} block128;++static inline void block128_copy_bytes(block128 *block, uint8_t *src, uint32_t len)+{+	int i;+	for (i = 0; i < len; i++) block->b[i] = src[i];+}++static inline void block128_copy(block128 *d, block128 *s)+{+	d->q[0] = s->q[0]; d->q[1] = s->q[1];+}++static inline void block128_zero(block128 *d)+{+	d->q[0] = 0; d->q[1] = 0;+}++static inline void block128_xor(block128 *d, block128 *s)+{+	d->q[0] ^= s->q[0];+	d->q[1] ^= s->q[1];+}++static inline void block128_vxor(block128 *d, block128 *s1, block128 *s2)+{+	d->q[0] = s1->q[0] ^ s2->q[0];+	d->q[1] = s1->q[1] ^ s2->q[1];+}++static inline void block128_xor_bytes(block128 *block, uint8_t *src, uint32_t len)+{+	int i;+	for (i = 0; i < len; i++) block->b[i] ^= src[i];+}++static inline void block128_inc_be(block128 *b)+{+	uint64_t v = be64_to_cpu(b->q[1]);+	if (++v == 0) {+		b->q[0] = cpu_to_be64(be64_to_cpu(b->q[0]) + 1);+		b->q[1] = 0;+	} else+		b->q[1] = cpu_to_be64(v);+}++#endif
+ cipher-aes128.cabal view
@@ -0,0 +1,39 @@+-- Initial cipher.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                cipher-aes128+version:             0.1+synopsis:            AES128 using AES-NI when available.+description:         AES128 with crypto-api instances and a trampoline between Vincent Hanquez's C-based and x86 NI-based AES.  Patches welcome to add additional high-performance backends (ARM?)+license:             BSD3+license-file:        LICENSE+author:              Thomas M. DuBuisson, Vincent Hanquez (See AUTHORS file)+maintainer:          thomas.dubuisson@gmail.com+copyright:           Thomas M. DuBuisson+category:            Cryptography+build-type:          Custom+cabal-version:       >=1.12++extra-source-files:       ./cbits/include/aes.h+                        , ./cbits/include/aes_generic.h+                        , ./cbits/include/aes_types.h+                        , ./cbits/include/aes_x86ni.h+                        , ./cbits/include/bitfn.h+                        , ./cbits/include/block128.h+                        , ./cbits/aes/LICENSE+                        , AUTHORS+library+  default-language:    Haskell2010+  exposed-modules:     Crypto.Cipher.AES128, Crypto.Cipher.AES128.Internal+  build-depends:       base >=4.5 && < 5,+                       bytestring,+                       crypto-api,+                       tagged,+                       cereal+  ghc-options:         -Wall -O2++  c-sources:              ./cbits/aes/aes.c+                        , ./cbits/aes/ni/aes_x86ni.c+                        , ./cbits/aes/generic/aes_generic.c+  include-dirs:        cbits/include+  cc-options:          -O3