packages feed

intel-aes (empty) → 0.1.1

raw patch · 42 files changed

+13828/−0 lines, 42 filesdep +DRBGdep +basedep +bytestringbuild-type:Customsetup-changed

Dependencies added: DRBG, base, bytestring, cereal, crypto-api, haskell98, intel-aes, process, random, rdtsc, split, tagged, time, unix

Files

+ Benchmark/BinSearch.hs view
@@ -0,0 +1,155 @@+#!/usr/bin/env runhaskell+++-- ---------------------------------------------------------------------------+--  Intel Concurrent Collections for Haskell+--  Copyright (c) 2010, Intel Corporation.+-- +--  This program is free software; you can redistribute it and/or modify it+--  under the terms and conditions of the GNU Lesser General Public License,+--  version 2.1, as published by the Free Software Foundation.+-- +--  This program is distributed in the hope it will be useful, but WITHOUT+--  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or+--  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for+--  more details.+-- +--  You should have received a copy of the GNU Lesser General Public License along with+--  this program; if not, write to the Free Software Foundation, Inc., +--  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.+-- ---------------------------------------------------------------------------+++-- This is a script used for timing the throughput of benchmarks that+-- take one argument and have linear complexity.+++module Benchmark.BinSearch +    (+      binSearch+    )+where++import Control.Monad+import Data.Time.Clock -- Not in 6.10+import Data.List+import Data.IORef+import System+import System.IO+import System.Cmd+import System.Exit+import Debug.Trace++-- In seconds:+--desired_exec_length = 3++++-- | Binary search for the number of inputs to a computation that+-- | makes it take a specified time in seconds.+--+-- > binSearch verbose N (min,max) kernel+--+-- | binSearch will find the right input size that results in a time+-- | between min and max, then it will then run for N trials and+-- | return the median (input,time-in-seconds) pair.+binSearch :: Bool -> Integer -> (Double,Double) -> (Integer -> IO ()) -> IO (Integer, Double)+binSearch verbose trials (min,max) kernel =+  do +     when(verbose)$ putStrLn$ "[binsearch] Binary search for input size resulting in time in range "++ show (min,max)++     let desired_exec_length = 1.0+	 good_trial t = (toRational t <= toRational max) && (toRational t >= toRational min)++	 --loop :: Bool -> [String] -> Int -> Integer -> IO ()++	 -- At some point we must give up...+	 loop n | n > (2 ^ 100) = error "ERROR binSearch: This function doesn't seem to scale in proportion to its last argument."++	 -- Not allowed to have "0" size input, bump it back to one:+	 loop 0 = loop 1++	 loop n = +	    do +	       when(verbose)$ putStr$ "[binsearch:"++ show n ++ "] "+	       -- hFlush stdout++	       time <- timeit$ kernel n++	       when(verbose)$ putStrLn$ "Time consumed: "++ show time+	       -- hFlush stdout+	       let rate = fromIntegral n / time++	       -- [2010.06.09] Introducing a small fudge factor to help our guess get over the line: +	       let initial_fudge_factor = 1.10+		   fudge_factor = 1.01 -- Even in the steady state we fudge a little+		   guess = desired_exec_length * rate ++   -- TODO: We should keep more history here so that we don't re-explore input space we have already explored.+   --       This is a balancing act because of randomness in execution time.++	       if good_trial time+		then do +			when(verbose)$ putStrLn$ "[binsearch] Time in range.  LOCKING input size and performing remaining trials."+			print_trial 1 n time+			lockin (trials-1) n [time]++		-- Here we're still in the doubling phase:+		else if time < 0.100 +		then loop (2*n)++		else do when(verbose)$ putStrLn$ "[binsearch] Estimated rate to be "++show (round$ rate)++" per second.  Trying to scale up..."++			-- Here we've exited the doubling phase, but we're making our first guess as to how big a real execution should be:+			if time > 0.100 && time < 0.33 * desired_exec_length+			   then do when(verbose)$ putStrLn$  "[binsearch]   (Fudging first guess a little bit extra)"+				   loop (round$ guess * initial_fudge_factor)+			   else    loop (round$ guess * fudge_factor)++ 	 -- Termination condition: Done with all trials.+         lockin 0 n log = do when(verbose)$ putStrLn$ "[binsearch] Time-per-unit for all trials: "++ +				            (concat $ intersperse " " (map (show . (/ toDouble n) . toDouble) $ sort log))+			     return (n, log !! ((length log) `quot` 2)) -- Take the median++         lockin trials_left n log = +		     do when(verbose)$ putStrLn$ "[binsearch]------------------------------------------------------------"+			time <- timeit$ kernel n+			-- hFlush stdout+			print_trial (trials - trials_left +1 ) n time+			-- when(verbose)$ hFlush stdout+			lockin (trials_left - 1) n (time : log)++         print_trial trialnum n time = +	     let rate = fromIntegral n / time+	         timeperunit = time / fromIntegral n+	     in+			when(verbose)$ putStrLn$ "[binsearch]  TRIAL: "++show trialnum +++				                 " secPerUnit: "++ showTime timeperunit ++ +						 " ratePerSec: "++ show (rate) ++ +						 " seconds: "++showTime time++++     (n,t) <- loop 1+     return (n, fromRational$ toRational t)++showTime t = show ((fromRational $ toRational t) :: Double)+toDouble :: Real a => a -> Double+toDouble = fromRational . toRational+++-- Could use cycle counters here.... but the point of this is to time+-- things on the order of a second.+timeit io = +    do strt <- getCurrentTime+       io       +       end  <- getCurrentTime+       return (diffUTCTime end strt)++test = +  binSearch True 3 (1.0, 1.05)+   (\n -> +    do v <- newIORef 0+       forM_ [1..n] $ \i -> do+         old <- readIORef v+         writeIORef v (old+i))
+ Codec/Crypto/ConvertRNG.hs view
@@ -0,0 +1,182 @@+{-|+   Module      :  Codec.Crypto.ConvertRNG+   Copyright   :  (c) Ryan Newton 2011+   License     :  BSD-style (see the file LICENSE)+   Maintainer  :  rrnewton@gmail.com+   Stability   :  experimental+   Portability :  portable, GHC++ This module bridges these three interfaces:++@+   Crypto.Classes.BlockCipher+   Crypto.Random.CryptoRandomGen+   System.Random.RandomGen+@++    Specifically, a block cipher can be converted to generate a+    @CryptoRandomGen@, which in turn can be converted to provide the+    @RandomGen@ interface.++  -}+{-# OPTIONS_GHC -fwarn-unused-imports #-}+{-# LANGUAGE  ScopedTypeVariables #-}+-- FlexibleInstances, EmptyDataDecls, FlexibleContexts, NamedFieldPuns, , ForeignFunctionInterface++module Codec.Crypto.ConvertRNG +  ( BCtoCRG(..), convertCRG     +  , CRGtoRG()+  , CRGtoRG0(..) -- Inefficient version for testing...+  )+where++import System.Random +import System.IO.Unsafe (unsafePerformIO)+import GHC.IO (unsafeDupablePerformIO)++-- import Data.List+import Data.Word+import Data.Tagged+import Data.Serialize++import qualified Data.Bits+import qualified Data.ByteString as B+-- import qualified Data.ByteString.Char8 as BC+import qualified Data.ByteString.Internal as BI++-- import Crypto.Random.DRBG ()+-- import Crypto.Modes++import Crypto.Random (CryptoRandomGen(..), GenError(..), splitGen, genBytes)+import Crypto.Classes (BlockCipher(..), blockSizeBytes)+import Crypto.Types (ByteLength)++import Control.Monad+-- import Foreign.Ptr+import qualified Foreign.ForeignPtr as FP+import Foreign.Storable+++----------------------------------------------------------------------------------------------------+-- Converting CryptoRandomGen to RandomGen+------------------------------------------++-- There's a potential overlapping instances problem here.  Someone+-- may want to do their own RandomGen instance, creating a problem+-- with this:+--+--   instance CryptoRandomGen g => RandomGen g where +--+-- NOTE: The above would also be an undecidable instance.  Another+-- option is to have a type used just for lifting.  See below.+++-- | Converting CryptoRandomGen to RandomGen.+--   This naive version is probably pretty inefficent:+data CRGtoRG0 a = CRGtoRG0 a+instance CryptoRandomGen g => RandomGen (CRGtoRG0 g) where +   next  (CRGtoRG0 g) = +--       case genBytes (max bytes_in_int (keyLength g `quot` 8)) g of +       case genBytes bytes_in_int g of +         Left err -> error$ "CryptoRandomGen genBytes error: " ++ show err+	 Right (bytes,g') -> +           case decode bytes of +	      Left err -> error$ "Deserialization error:"++ show err+	      Right n -> (n, CRGtoRG0 g')+	     +   split (CRGtoRG0 g) = +       case splitGen g of +         Left err      -> error$ "CryptoRandomGen splitGen error:"++ show err+	 Right (g1,g2) -> (CRGtoRG0 g1, CRGtoRG0 g2)++-- Another option would be to amortize overhead by generating a large+-- buffer of random bits at once.+-- data CRGtoRG a = CRGtoRG a BUFFER INDEX++-- Any better way to do this?+bytes_in_int = (round $ 1 + logBase 2 (fromIntegral (maxBound :: Int)))  `quot` 8+-- steps = 128 `quot` bits_in_int++------------------------------------------------------------+-- | Converting CryptoRandomGen to RandomGen.+--   Keep a buffer of random bits and an index into that buffer.+data CRGtoRG a = CRGtoRG a +    {-#UNPACK#-}!         (FP.ForeignPtr Int)+    {-#UNPACK#-}!         Int++instance CryptoRandomGen g => RandomGen (CRGtoRG g) where +   next (CRGtoRG g _ ind) | ind == bufsize = next (convertCRG g) -- Refill the buffer+   next (CRGtoRG g buf ind) = +       -- As long as this memory is in use it will not be modified.+       -- The peek action should therefore be dupable:+       unsafeDupablePerformIO $ +         FP.withForeignPtr buf $ \ ptr -> +           do x <- peekElemOff ptr ind +	      return (x, CRGtoRG g buf (ind+1))+	     +   split (CRGtoRG g buf ind) = +       case splitGen g of +         Left err      -> error$ "CryptoRandomGen splitGen error:"++ show err+	 Right (g1,g2) -> (CRGtoRG g1 buf ind, convertCRG g2)+++-- | The constructor for CRGtoRG values.+convertCRG :: CryptoRandomGen g => g -> CRGtoRG g+convertCRG crg = CRGtoRG g' (FP.castForeignPtr ptr) 0+ where +  (ptr,_,_)     = BI.toForeignPtr bs+  Right (bs,g') = genBytes (bufsize * bytes_in_int) crg+++-- How many 8 byte chunks should we buffer each time?+-- TODO: Autotune this...+bufsize = 256++++----------------------------------------------------------------------------------------------------+-- We would also like every BlockCipher to constitute a valid CryptoRandomGen.+-- Again there's the tension with UndecidableInstances vs explicit lifting.++-- | A BlockCipher can generate random numbers.+--   When lifting we include a counter which increments as random numbers are generated:+data BCtoCRG a = BCtoCRG a Word64++instance BlockCipher x => CryptoRandomGen (BCtoCRG x) where +  newGen  bytes = case buildKey bytes of Nothing -> Left NotEnoughEntropy +					 Just x  -> Right (BCtoCRG x 0)+  genSeedLength = Tagged 128++  -- If this is called for less than blockSize data there's some waste but it should work.+  genBytes req (BCtoCRG (bcgen :: k) counter) = +      -- What's the most efficient way to do this?+      unsafePerformIO $ do  -- Potentially heavyweight... not allowing dupable.+--      unsafeDupablePerformIO $ do+	-- Number of times to stamp out the counter:+        let bsize = untag (blockSizeBytes :: Tagged k ByteLength)+	    numstamps = (req + 7) `quot` 8+	    numblocks = (req + bsize - 1) `quot` bsize+	    total     = max (numstamps * 8) (numblocks * bsize)++        -- putStrLn$ "[temp] requested "++show req++" bytes, stamping  "++show (numstamps*8)+++	-- 	  " into "++show numblocks++" block(s), output buf size "++show total++        buf :: FP.ForeignPtr Word64 <- FP.mallocForeignPtrBytes total+	FP.withForeignPtr buf $ \ptr -> +	  forM_ [0..numstamps-1] $ \i -> +	    pokeElemOff ptr i (counter + fromIntegral i)+        let cipher = encryptBlock bcgen (BI.fromForeignPtr (FP.castForeignPtr buf) 0 total)+	    newgen = BCtoCRG bcgen (counter + fromIntegral numstamps)+	-- At the end we may have requested more bytes than needed, so we might crop:+	if req==total then return$ Right (cipher, newgen)+	              else return$ Right (B.take req cipher, newgen)++  reseed bs (BCtoCRG k _) = newGen (xorExtendBS (encode k) bs)++xorExtendBS a b = B.append (B.pack$ B.zipWith Data.Bits.xor a b) rem+      where+      al = B.length a+      bl = B.length b+      rem | bl > al   = B.drop al b+          | otherwise = B.drop bl a+
+ Codec/Crypto/GladmanAES.hsc view
@@ -0,0 +1,194 @@+-- | ECB AES operation.  This code is based on the "AES" package from+-- Svein Ove Aas (University of Tromsø), though it is heavily modified+-- and any bugs should be blamed on me, Thomas M. DuBuisson.+{-# LANGUAGE FlexibleInstances, EmptyDataDecls, FlexibleContexts, +    ForeignFunctionInterface, ViewPatterns,+    ScopedTypeVariables+    #-}+{-# CFILES cbits/gladman/aescrypt.c cbits/gladman/aeskey.c cbits/gladman/aestab.c cbits/gladman/aes_modes.c #-}+module Codec.Crypto.GladmanAES+	( AES+	, N128, N192, N256+	, module Crypto.Classes+	, module Crypto.Modes) where++import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as BI+import Crypto.Modes+import Crypto.Classes+import Crypto.Types+import Data.Tagged+import Data.Serialize++import Foreign+import Control.Applicative+import Control.Monad++-- import Crypto.Random (CryptoRandomGen(newGen))+-- The following line will cause a link problem currently [2011.02.02]:+     -- Linking dist/build/benchmark-intel-aes-rng/benchmark-intel-aes-rng ...+     -- /home/newton/Dropbox/working_copies/intel-aes/dist/build/libHSintel-aes-0.1.1.a(GladmanAES.o): In function `s3ho_info':+     -- (.text+0x34c3): undefined reference to `__stginit_intelzmaeszm0zi1zi1_CodecziCryptoziConvertRNG_'+     -- collect2: ld returned 1 exit status+-- import qualified Codec.Crypto.ConvertRNG as CR++#include "gladman/aesopt.h"+#include "gladman/aes.h"+#include "gladman/aestab.h"+#include "gladman/brg_endian.h"+#include "gladman/ctr_inc.h"++data N128+data N192+data N256++data AES n = AES+		{ encCtx :: EncryptCtxP+		, decCtx :: DecryptCtxP+		, aesKeyRaw :: B.ByteString }+++-- Because of the above link problem I can't move these:+{-+mkAESGen :: Int -> CR.CRGtoRG (CR.BCtoCRG (AES N128))+mkAESGen int = CR.convertCRG gen+ where+  Right (gen :: CR.BCtoCRG (AES N128)) = newGen (B.append halfseed halfseed )+  halfseed = encode word64+  word64 = fromIntegral int :: Word64++mkAESGen0 :: Int -> CR.CRGtoRG0 (CR.BCtoCRG (AES N128))+mkAESGen0 int = CR.CRGtoRG0 gen+ where+  Right (gen :: CR.BCtoCRG (AES N128)) = newGen (B.append halfseed halfseed )+  halfseed = encode word64+  word64 = fromIntegral int :: Word64+ -}++--------------------------------------------------------------------------------++-- | Create an encryption/decryption context for incremental+-- encryption/decryption+--+-- You may create an ECB context this way, in which case you may pass+-- undefined for the IV+newCtx :: B.ByteString -> IO (AES n)+newCtx key = do+	e <- (encryptCtx key)+	d <- (decryptCtx key)+	return $ AES e d key++instance BlockCipher (AES N128) where+	blockSize = Tagged 128+	encryptBlock = aesEnc+	decryptBlock = aesDec+	buildKey = aesBK 128+	keyLength = aesKL++instance BlockCipher (AES N192) where+	blockSize = Tagged 128+	encryptBlock = aesEnc+	decryptBlock = aesDec+	buildKey = aesBK 192+	keyLength = aesKL++instance BlockCipher (AES N256) where+	blockSize = Tagged 128+	encryptBlock = aesEnc+	decryptBlock = aesDec+	buildKey = aesBK 256+	keyLength = aesKL+++aesEnc :: AES n -> B.ByteString -> B.ByteString+aesEnc k m = unsafePerformIO $ call _aes_ecb_encrypt (encCtx k) m++aesDec :: AES n -> B.ByteString -> B.ByteString+aesDec k m = unsafePerformIO $ call _aes_ecb_decrypt (decCtx k) m++aesBK :: Int -> B.ByteString -> Maybe (AES n)+aesBK n bs+  | B.length bs == n `div` 8 = Just $ unsafePerformIO (newCtx bs)+  | otherwise                = Nothing++aesKL :: AES n -> BitLength+aesKL = (*8) . B.length . aesKeyRaw++instance Serialize (AES N128) where+	get = getGeneral 16+	put = putByteString . aesKeyRaw++instance Serialize (AES N192) where+	get = getGeneral 24+	put = putByteString . aesKeyRaw++instance Serialize (AES N256) where+	get = getGeneral 32+	put = putByteString . aesKeyRaw++getGeneral :: BlockCipher (AES n) => Int -> Get (AES n)+getGeneral n = do+	bs <- getByteString n+	case buildKey bs of+		Nothing -> fail "Could not build key from serialized bytestring"+		Just x  -> return x++call :: (Ptr b -> Ptr Word8 -> Int -> Ptr a -> IO Int)+       -> ForeignPtr a -> B.ByteString -> IO B.ByteString+call f ctx (BI.toForeignPtr -> (bs,offset,len)) =+  withForeignPtr ctx $ \ctxp ->+  withForeignPtr bs $ \bsp ->+  BI.create len $ \obuf ->+  ensure $ f (bsp `plusPtr` offset) obuf len ctxp++foreign import ccall unsafe "aes_ecb_encrypt" _aes_ecb_encrypt+  :: Ptr Word8 -> Ptr Word8 -> Int -> Ptr EncryptCtxStruct -> IO Int+foreign import ccall unsafe "aes_ecb_decrypt" _aes_ecb_decrypt+  :: Ptr Word8 -> Ptr Word8 -> Int -> Ptr DecryptCtxStruct -> IO Int++type EncryptCtxP = ForeignPtr EncryptCtxStruct++type DecryptCtxP = ForeignPtr DecryptCtxStruct++data EncryptCtxStruct+instance Storable EncryptCtxStruct where+  sizeOf _ = #size aes_encrypt_ctx+  alignment _ = 16 -- FIXME: Maybe overkill, maybe underkill, definitely iffy++data DecryptCtxStruct+instance Storable DecryptCtxStruct where+  sizeOf _ = #size aes_decrypt_ctx+  alignment _ = 16++wrap :: Int -> Bool+wrap r | r == (#const EXIT_SUCCESS) = True+       | otherwise = False++ensure :: IO Int -> IO ()+ensure act = do+  r <- wrap <$> act+  unless r (fail "AES function failed")++foreign import ccall unsafe "aes_encrypt_key" _aes_encrypt_key +  :: Ptr Word8 -> Int -> Ptr EncryptCtxStruct -> IO Int++encryptCtx :: B.ByteString -> IO EncryptCtxP+encryptCtx bs = do+  ctx <- mallocForeignPtr+  let (key,offset,len) = BI.toForeignPtr bs+  withForeignPtr ctx $ \ctx' ->+    withForeignPtr key $ \key' ->+    ensure $ _aes_encrypt_key (key' `plusPtr` offset) len ctx'+  return ctx++foreign import ccall unsafe "aes_decrypt_key" _aes_decrypt_key +  :: Ptr Word8 -> Int -> Ptr DecryptCtxStruct -> IO Int++decryptCtx :: B.ByteString -> IO DecryptCtxP+decryptCtx bs = do+  ctx <- mallocForeignPtr+  let (key,offset,len) = BI.toForeignPtr bs+  withForeignPtr ctx $ \ctx' ->+    withForeignPtr key $ \key' ->+    ensure $ _aes_decrypt_key (key' `plusPtr` offset) len ctx'+  return ctx
+ Codec/Crypto/IntelAES.hs view
@@ -0,0 +1,125 @@+{-|+     Module      :  Codec.Crypto.IntelAES+     Copyright   :  (c) Ryan Newton 2011+     License     :  BSD-style (see the file LICENSE)+     Maintainer  :  rrnewton@gmail.com+     Stability   :  experimental+     Portability :  linux only (NEEDS PORTING)++     This module provides an AES implementation that will test the CPU+     ID and use hardware acceleration where available, otherwise it will+     fall back to Dr. Brian Gladman's software implementation.++     This module also exports a random number generator based on AES+     both using the System.Random.RandomGen interface and the+     Codec.Crypto.Random.++  -}+{-# OPTIONS_GHC -fwarn-unused-imports #-}+{-# LANGUAGE ForeignFunctionInterface, CPP, ScopedTypeVariables  #-}++module Codec.Crypto.IntelAES+    (+      mkAESGen,+      CompoundAESRNG(), +     -- Plus, instances exported of course.+      testIntelAES+    )+where ++import qualified Codec.Crypto.IntelAES.AESNI      as NI+import qualified Codec.Crypto.GladmanAES as GA+import GHC.IO (unsafeDupablePerformIO)+import Data.Tagged+import Data.Word+import Data.Serialize+import qualified Data.ByteString as B+import Crypto.Random (CryptoRandomGen(..), GenError(..), splitGen, genBytes)+import Crypto.Types+import Codec.Crypto.ConvertRNG +import Debug.Trace++newtype CompoundCRG = +  CompoundCRG +   (Either (BCtoCRG (NI.IntelAES NI.N128))+	   (BCtoCRG (GA.AES GA.N128)))++-- | A type representing an AES-based random number generator which+--   will use AESNI instructions when available, and invoke the+--   portable Gladman implementation when not.+type CompoundAESRNG = CRGtoRG CompoundCRG++-- | Simple function to create a random number generator from an Int,+--   analogous to `System.Random.newStdGen`.  Only 128-bit encryption+--   is provided for now.+mkAESGen :: Int -> CompoundAESRNG+mkAESGen int = convertCRG gen+   where+  Right (gen :: CompoundCRG) = newGen (B.append halfseed halfseed )+  halfseed = encode word64+  word64 = fromIntegral int :: Word64++++-- foreign import ccall unsafe "iaesni.h" check_for_aes_instructions :: IO Bool+foreign import ccall unsafe "iaesni.h" check_for_aes_instructions :: Bool+++{-# INLINE mapRight #-}+mapRight fn x@(Left _) = x+mapRight fn (Right x)  = Right$ fn x++{-# INLINE mapSnd #-}+mapSnd fn (x,y) = (x,fn y)+++instance CryptoRandomGen CompoundCRG where ++--  newGen :: B.ByteString -> Either GenError CompoundCRG+  newGen = +--     if unsafeDupablePerformIO check_for_aes_instructions+     trace ("Checked for AES instructions: "++ show check_for_aes_instructions)$+     if check_for_aes_instructions+     -- Ick, boilerplate:+     then \bytes -> case newGen bytes of Left err  -> Left err+					 Right gen -> Right$ CompoundCRG$ Left gen+     else \bytes -> case newGen bytes of Left err  -> Left err+					 Right gen -> Right$ CompoundCRG$ Right gen++  genSeedLength = Tagged 128++ +  -- ByteLength -> CompoundCRG -> Either GenError (B.ByteString, CompoundCRG)+  genBytes req (CompoundCRG (Left gen)) = +-- Let's try to reduce that boilerplate if we can...+#if 0+    mapRight (mapSnd (CompoundCRG . Left) ) $ genBytes req gen+#else+    case genBytes req gen of +      Left  err  -> Left err+      Right (bytes,gen') -> Right (bytes, CompoundCRG (Left gen'))+#endif++-- <boilerplate> OUCH+  genBytes req (CompoundCRG (Right gen)) = +    case genBytes req gen of +      Left  err  -> Left err+      Right (bytes,gen') -> Right (bytes, CompoundCRG (Right gen'))+  reseed bs (CompoundCRG (Left gen)) = +    case reseed bs gen of +      Left  err  -> Left err+      Right gen' -> Right (CompoundCRG (Left gen'))+  reseed bs (CompoundCRG (Right gen)) = +    case reseed bs gen of +      Left  err  -> Left err+      Right gen' -> Right (CompoundCRG (Right gen'))+-- </boilerplate>++++testIntelAES = do +  putStrLn$ "Running crude tests."+--  b <- check_for_aes_instructions+  let b = check_for_aes_instructions+  putStrLn$ "Machine supports AESNI: "++ show b+
+ Codec/Crypto/IntelAES/AESNI.hs view
@@ -0,0 +1,289 @@+{- | +     Module      :  Codec.Crypto.IntelAES.AESNI+     Copyright   :  (c) Ryan Newton 2011+     License     :  BSD-style (see the file LICENSE)    +     Maintainer  :  rrnewton@gmail.com+     Stability   :  experimental+     Portability :  linux only (NEEDS PORTING)+++     This module provides an AES implementation that /assumes/ AES-NI+     instructions are available on the processor.  It will be+     non-portable as a result.  Therefore, for most purposes+     Codec.Crypto.IntelAES should be used instead.++     Note: This module is simply a wrapper around the Intel-provided+     AESNI sample library, found here:++     <http://software.intel.com/en-us/articles/download-the-intel-aesni-sample-library/>++ -}+{-# OPTIONS_GHC -fwarn-unused-imports #-}+{-# LANGUAGE FlexibleInstances, EmptyDataDecls, FlexibleContexts, NamedFieldPuns,+     ScopedTypeVariables, ForeignFunctionInterface #-}++module Codec.Crypto.IntelAES.AESNI+    (+      testAESNI+    , mkAESGen, SimpleAESRNG+    , mkAESGen192, mkAESGen256++    -- Inefficient version for testing:+    , mkAESGen0, SimpleAESRNG0+    , IntelAES, N128, N192, N256+     -- Plus, instances exported of course.+    )+where ++import Codec.Crypto.ConvertRNG++import System.Random +import System.IO.Unsafe (unsafePerformIO)+-- import GHC.IO (unsafeDupablePerformIO)++import Data.List+import Data.Word+import Data.Tagged+import Data.Serialize++import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as BI++import Crypto.Random.DRBG ()++import Crypto.Random (CryptoRandomGen(..))+import Crypto.Classes (BlockCipher(..))++import Control.Monad+import Foreign.Ptr+import qualified Foreign.ForeignPtr as FP+import Foreign.Storable++----------------------------------------------------------------------------------------------------++-- | The type of a simple 'System.Random.RandomGen' instance.+type SimpleAESRNG = CRGtoRG (BCtoCRG (IntelAES N128))++-- | Expose a simple System.Random.RandomGen interface using 128 bit encryption.  +mkAESGen :: Int -> SimpleAESRNG+mkAESGen int = convertCRG gen+ where+  Right (gen :: BCtoCRG (IntelAES N128)) = newGen (B.append halfseed halfseed )+  halfseed = encode word64+  word64 = fromIntegral int :: Word64++-- | Same thing for 192 bit encryption.+mkAESGen192 :: B.ByteString -> CRGtoRG (BCtoCRG (IntelAES N192))+mkAESGen192 seed = convertCRG gen+ where+  Right (gen :: BCtoCRG (IntelAES N192)) = newGen (B.take 24 seed)++-- | Ditto for 256 bit encryption.+mkAESGen256 :: B.ByteString -> CRGtoRG (BCtoCRG (IntelAES N256))+mkAESGen256 seed = convertCRG gen+ where+  Right (gen :: BCtoCRG (IntelAES N256)) = newGen (B.take 24 seed)++++-- | TEMP: Inefficient version for testing.+type SimpleAESRNG0 = CRGtoRG0 (BCtoCRG (IntelAES N128))+mkAESGen0 :: Int -> SimpleAESRNG0+mkAESGen0 int = CRGtoRG0 gen+ where+  Right (gen :: BCtoCRG (IntelAES N128)) = newGen (B.append halfseed halfseed )+  halfseed = encode word64+  word64 = fromIntegral int :: Word64+++----------------------------------------------------------------------------------------------------++type PlainText   = Ptr Word8+type CipherText  = Ptr Word8+type Key         = Ptr Word8+type NullResult = IO ()++foreign import ccall unsafe "iaesni.h" intel_AES_enc128     :: PlainText -> CipherText -> Key -> Int -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_enc128_CBC :: PlainText -> CipherText -> Key -> Int -> Ptr Word8 -> NullResult+-- Copy/paste:+foreign import ccall unsafe "iaesni.h" intel_AES_enc192     :: PlainText -> CipherText -> Key -> Int -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_enc192_CBC :: PlainText -> CipherText -> Key -> Int -> Ptr Word8 -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_enc256     :: PlainText -> CipherText -> Key -> Int -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_enc256_CBC :: PlainText -> CipherText -> Key -> Int -> Ptr Word8 -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_dec128     :: CipherText -> PlainText -> Key -> Int -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_dec128_CBC :: CipherText -> PlainText -> Key -> Int -> Ptr Word8 -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_dec192     :: CipherText -> PlainText -> Key -> Int -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_dec192_CBC :: CipherText -> PlainText -> Key -> Int -> Ptr Word8 -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_dec256     :: CipherText -> PlainText -> Key -> Int -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_dec256_CBC :: CipherText -> PlainText -> Key -> Int -> Ptr Word8 -> NullResult++foreign import ccall unsafe "iaesni.h" intel_AES_encdec128_CTR :: Ptr Word8 -> Ptr Word8 -> Key -> Int -> Ptr Word8 -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_encdec192_CTR :: Ptr Word8 -> Ptr Word8 -> Key -> Int -> Ptr Word8 -> NullResult+foreign import ccall unsafe "iaesni.h" intel_AES_encdec256_CTR :: Ptr Word8 -> Ptr Word8 -> Key -> Int -> Ptr Word8 -> NullResult+++foreign import ccall unsafe "stdlib.h" malloc :: Int -> IO (Ptr Word8)+foreign import ccall unsafe "stdlib.h" calloc :: Int -> Int -> IO (Ptr Word8)++-- foreign import ccall unsafe "c_test.c" temp_test128 :: IO ()++----------------------------------------------------------------------------------------------------++-- Haskell datatypes to model the different AES modes:+data N128+data N192+data N256++data IntelAES n = IntelAES { aesKeyRaw :: B.ByteString }++{-# INLINE unpackKey #-}+unpackKey (IntelAES {aesKeyRaw}) = kptr+  -- TODO: ASSERT that key is the right length and offset is zero...+  where +  (kptr,koff,klen) = BI.toForeignPtr aesKeyRaw++{-# INLINE template #-}+template core keysize ctx@(IntelAES {aesKeyRaw}) plaintext = +--	 unsafeDupablePerformIO $+	 unsafePerformIO $+	 do let kfptr                   = unpackKey ctx +		(in_fptr,in_off,in_len) = BI.toForeignPtr plaintext+		(blocks,r) = quotRem in_len keysize+	    -- The buffer should be a multiple of the key size (128/192,256 bits):+	    when (r > 0)$ +	       error$ "encryptBlock: block size "++show in_len+++		      " bytes , but with AES implementation block size must be a multiple of "++show keysize++	    output <- FP.mallocForeignPtrBytes in_len +	    FP.withForeignPtr kfptr $ \ keyptr -> +	      FP.withForeignPtr in_fptr $ \ inptr -> +		FP.withForeignPtr output  $ \ outptr -> +		  core inptr outptr keyptr blocks++	    return (BI.fromForeignPtr output 0 in_len)++instance BlockCipher (IntelAES N128) where+	blockSize    = Tagged 128+	encryptBlock = template intel_AES_enc128 16+	decryptBlock = template intel_AES_dec128 16+        -- What's the right behavior here?  Currently this refuses to+        -- generate keys if given an insufficient # of bytes.+	buildKey bytes | B.length bytes >= 16 = Just$ newCtx bytes+        buildKey _     | otherwise            = Nothing+	keyLength (IntelAES {aesKeyRaw}) = B.length aesKeyRaw * 8 -- bits++instance Serialize (IntelAES N128) where+	get = getGeneral 16+	put = putByteString . aesKeyRaw++-- <boilerplate>+instance BlockCipher (IntelAES N192) where+	blockSize    = Tagged 192+	encryptBlock = template intel_AES_enc192 24+	decryptBlock = template intel_AES_dec192 24+	buildKey bytes | B.length bytes >= 24 = Just$ newCtx bytes+        buildKey _     | otherwise            = Nothing+	keyLength (IntelAES {aesKeyRaw}) = B.length aesKeyRaw+instance Serialize (IntelAES N192) where+	get = getGeneral 24+	put = putByteString . aesKeyRaw+instance BlockCipher (IntelAES N256) where+	blockSize    = Tagged 192+	encryptBlock = template intel_AES_enc256 32+	decryptBlock = template intel_AES_dec256 32+	buildKey bytes | B.length bytes >= 32 = Just$ newCtx bytes+        buildKey _     | otherwise            = Nothing+	keyLength (IntelAES {aesKeyRaw}) = B.length aesKeyRaw+instance Serialize (IntelAES N256) where+	get = getGeneral 32+	put = putByteString . aesKeyRaw+-- </boilerplate>+++getGeneral :: BlockCipher (IntelAES n) => Int -> Get (IntelAES n)+getGeneral n = do+	bs <- getByteString n+	case buildKey bs of+		Nothing -> fail "Could not build key from serialized bytestring"+		Just x  -> return x++newCtx :: B.ByteString -> IntelAES n+newCtx key = IntelAES key++----------------------------------------------------------------------------------------------------+-- Testing+  ------------------------------------------------------------++unpack_ptr :: Storable a => Ptr a -> Int -> IO [a]+unpack_ptr ptr len = loop len []+  where +  loop 0 acc = return acc+  loop i acc = do x    <- peekElemOff ptr (i-1)+		  loop (i-1) (x:acc)+++-- | This is not a meaningful test yet... one option would be to+--   reproduce the tests in aessample.c+testAESNI :: IO ()+testAESNI = do +  let bytes = 256+  plaintext  <- calloc bytes 1+  key        <- calloc 16 1+  ciphertext <- calloc bytes 1++  forM [0..bytes-1] $ \i -> do +    pokeElemOff plaintext i (fromIntegral i)++  forM [0..15] $ \i -> do +    pokeElemOff key i (fromIntegral i)++  putStrLn$ "Plaintext:" +  ls <- unpack_ptr plaintext bytes+  print ls++  putStrLn$ "Key:" +  ls <- unpack_ptr key 16+  print ls++  putStrLn$ "Cipher text:" +  ls <- unpack_ptr ciphertext bytes+  print ls++  putStrLn$ "\nCalling foreign AES encode routine: byte"+  -- Divide byte length by 128 bits (16 bytes):+  intel_AES_enc256 plaintext ciphertext key (bytes `quot` 16)+  putStrLn$ "Done with foreign call"++  putStrLn$ "Cipher text:" +  ls <- unpack_ptr ciphertext bytes+  print ls++  putStrLn$ "================================================================================" +  putStrLn$ "\nNow let's try it as a block cypher... encrypt increasing bytes:"+  let inp = B.pack $ take bytes [0..]+      ctxt :: IntelAES N128 = newCtx (B.take 16 inp) +      cipher = encryptBlock ctxt inp++      backagain = decryptBlock ctxt cipher++  putStrLn$ "\nCiphertext: "++ show (B.unpack cipher)+  putStrLn$ "\nAnd back again: "++ show (B.unpack backagain)++  when (not$ backagain == inp) $+    error "Test failed! Round-trip did not get us back to the plaintext!"++  putStrLn$ "================================================================================" +  putStrLn$ "\nFinally lets use it to generate some random numbers:"+  let +      gen2 = mkAESGen 92438653296+      fn (0,_) = Nothing+      fn (i,g) = let (n,g') = next g in Just (n, (i-1,g'))+      nums = unfoldr fn (20,gen2)+  putStrLn$ "Randoms: " ++ show nums++  ------------------------------------------------------------+  putStrLn$ "Done."+  -- putStrLn$ "Next calling test routine in C:"+  -- temp_test128 +  -- putStrLn$ "Done with that test routine"+  
+ Codec/Encryption/AES.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE TypeSynonymInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Codec.Encryption.AES+-- Copyright   :  (c) Dominic Steinitz 2004+-- License     :  BSD-style (see the file ReadMe.tex)+-- +-- Maintainer  :  dominic.steinitz@blueyonder.co.uk+-- Stability   :  experimental+-- Portability :  portable+--+-- Pure Haskell AES implementation.+-- +-- Takes the AES module supplied by Lukasz Anforowicz and wraps it so it can+-- used with the standard modes.+--+-----------------------------------------------------------------------------++module Codec.Encryption.AES (+   -- * Function Types +   encrypt, decrypt, AESKey) where++import Codec.Encryption.AESAux+import Data.LargeWord+import Codec.Utils+import Data.Word+import Data.Bits++class (Bits a, Integral a) => AESKeyIndirection a+class AESKeyIndirection a => AESKey a++instance AESKeyIndirection Word128+instance AESKeyIndirection Word192+instance AESKeyIndirection Word256++instance AESKey Word128+instance AESKey Word192+instance AESKey Word256++-- | Basic AES encryption which takes a key and a block of plaintext +-- and returns the encrypted block of ciphertext according to the standard.++encrypt :: AESKey a => a -> Word128 -> Word128+encrypt k p = +   case bitSize k of+      128 -> f aes128Encrypt k p+      192 -> f aes192Encrypt k p+      256 -> f aes256Encrypt k p++f g k p = +   fromIntegral $ fromOctets 256 $ +      g (i2osp (bitSize k `div` bitSize (0::Octet)) $ fromIntegral k) +        (i2osp (bitSize p `div` bitSize (0::Octet)) $ fromIntegral p)++-- | Basic AES decryption which takes a key and a block of ciphertext and+-- returns the decrypted block of plaintext according to the standard.++decrypt :: AESKey a => a -> Word128 -> Word128+decrypt k p = +   case bitSize k of+      128 -> f aes128Decrypt k p+      192 -> f aes192Decrypt k p+      256 -> f aes256Decrypt k p+
+ Codec/Encryption/AESAux.hs view
@@ -0,0 +1,1008 @@+-- | Advanced Encryption System (specification can be found in FIPS-197)
+module Codec.Encryption.AESAux(
+	aes128Encrypt,
+	aes192Encrypt,
+	aes256Encrypt,
+	aes128Decrypt,
+	aes192Decrypt,
+	aes256Decrypt,
+) where
+
+import Data.Bits
+import Data.Int(Int)
+import Data.Word(Word32)
+
+import Codec.Utils(Octet)
+
+aes128Encrypt :: [Octet] -- ^ key (16 octets)
+	      -> [Octet] -- ^ msg (16 octets)
+	      -> [Octet] -- ^ enciphered msg (16 octets)
+aes128Encrypt = aesEncrypt 10 4
+
+aes192Encrypt :: [Octet] -- ^ key (24 octets)
+	      -> [Octet] -- ^ msg (16 octets)
+	      -> [Octet] -- ^ enciphered msg (16 octets)
+aes192Encrypt = aesEncrypt 12 6
+
+aes256Encrypt :: [Octet] -- ^ key (32 octets)
+	      -> [Octet] -- ^ msg (16 octets)
+	      -> [Octet] -- ^ enciphered msg (16 octets)
+aes256Encrypt = aesEncrypt 14 8
+
+aes128Decrypt :: [Octet] -- ^ key (16 octets)
+	      -> [Octet] -- ^ enciphered msg (16 octets)
+	      -> [Octet] -- ^ deciphered msg (16 octets)
+aes128Decrypt = aesDecrypt 10 4
+
+aes192Decrypt :: [Octet] -- ^ key (24 octets)
+	      -> [Octet] -- ^ enciphered msg (16 octets)
+	      -> [Octet] -- ^ deciphered msg (16 octets)
+aes192Decrypt = aesDecrypt 12 6
+
+aes256Decrypt :: [Octet] -- ^ key (32 octets)
+	      -> [Octet] -- ^ enciphered msg (16 octets)
+	      -> [Octet] -- ^ deciphered msg (16 octets)
+aes256Decrypt = aesDecrypt 14 8
+
+aesEncrypt :: Int     -- ^ nr 
+	   -> Int     -- ^ nk
+	   -> [Octet] -- ^ key
+	   -> [Octet] -- ^ msg
+	   -> [Octet] -- ^ enciphered msg
+aesEncrypt nr nk key 
+		[i00, i10, i20, i30,
+		 i01, i11, i21, i31,
+		 i02, i12, i22, i32,
+		 i03, i13, i23, i33] =
+		[fo o00, fo o10, fo o20, fo o30,
+		 fo o01, fo o11, fo o21, fo o31,
+		 fo o02, fo o12, fo o22, fo o32,
+		 fo o03, fo o13, fo o23, fo o33]
+	where State (o00, o01, o02, o03)	 
+		    (o10, o11, o12, o13)	 
+		    (o20, o21, o22, o23)	 
+		    (o30, o31, o32, o33) = transform (
+		    	State(fi i00, fi i01, fi i02, fi i03)
+		    	     (fi i10, fi i11, fi i12, fi i13)
+		    	     (fi i20, fi i21, fi i22, fi i23)
+		    	     (fi i30, fi i31, fi i32, fi i33))
+	      fi = (fromIntegral :: Octet -> Word32)		     
+	      fo = (fromIntegral :: Word32 -> Octet)		     
+	      (kt0:kts) = genAddRoundKey (generateKeys nr nk key)
+	      transform = foldr (.) kt0 (reverse rest)
+	      mss = replicate (nr - 1) (mixColumns . shiftRows . subBytes)
+	      rest = zipWith (.) kts (mss ++ [shiftRows . subBytes ])
+	      
+
+aesDecrypt :: Int     -- ^ nr 
+	   -> Int     -- ^ nk
+	   -> [Octet] -- ^ key
+	   -> [Octet] -- ^ enciphered msg
+	   -> [Octet] -- ^ deciphered msg
+aesDecrypt nr nk key 
+		[i00, i10, i20, i30,
+		 i01, i11, i21, i31,
+		 i02, i12, i22, i32,
+		 i03, i13, i23, i33] =
+		[fo o00, fo o10, fo o20, fo o30,
+		 fo o01, fo o11, fo o21, fo o31,
+		 fo o02, fo o12, fo o22, fo o32,
+		 fo o03, fo o13, fo o23, fo o33]
+	where State (o00, o01, o02, o03)	 
+		    (o10, o11, o12, o13)	 
+		    (o20, o21, o22, o23)	 
+		    (o30, o31, o32, o33) = transform (
+		    	State(fi i00, fi i01, fi i02, fi i03)
+		    	     (fi i10, fi i11, fi i12, fi i13)
+		    	     (fi i20, fi i21, fi i22, fi i23)
+		    	     (fi i30, fi i31, fi i32, fi i33))
+	      fi = (fromIntegral :: Octet -> Word32)		     
+	      fo = (fromIntegral :: Word32 -> Octet)		     
+	      (kt0:kts) = reverse (genAddRoundKey (generateKeys nr nk key))
+	      transform = foldr (.) kt0 (reverse rest)
+	      ssm = replicate (nr - 1) 
+	      			(subBytesRev . shiftRowsRev . mixColumnsRev)
+	      rest = zipWith (.) kts ([subBytesRev . shiftRowsRev] ++ ssm)
+	      
+
+
+data State =  State !(Word32, Word32, Word32, Word32)
+		    !(Word32, Word32, Word32, Word32)
+		    !(Word32, Word32, Word32, Word32)
+		    !(Word32, Word32, Word32, Word32)
+
+sbox :: Word32 -> Word32
+sboxRev :: Word32 -> Word32
+
+sbox 0x00 = 0x63
+sbox 0x01 = 0x7C
+sbox 0x02 = 0x77
+sbox 0x03 = 0x7B
+sbox 0x04 = 0xF2
+sbox 0x05 = 0x6B
+sbox 0x06 = 0x6F
+sbox 0x07 = 0xC5
+
+sbox 0x08 = 0x30
+sbox 0x09 = 0x01
+sbox 0x0a = 0x67
+sbox 0x0b = 0x2B
+sbox 0x0c = 0xFE
+sbox 0x0d = 0xD7
+sbox 0x0e = 0xAB
+sbox 0x0f = 0x76
+
+sbox 0x10 = 0xCA
+sbox 0x11 = 0x82
+sbox 0x12 = 0xC9
+sbox 0x13 = 0x7D
+sbox 0x14 = 0xFA
+sbox 0x15 = 0x59
+sbox 0x16 = 0x47
+sbox 0x17 = 0xF0
+
+sbox 0x18 = 0xAD
+sbox 0x19 = 0xD4
+sbox 0x1a = 0xA2
+sbox 0x1b = 0xAF
+sbox 0x1c = 0x9C
+sbox 0x1d = 0xA4
+sbox 0x1e = 0x72
+sbox 0x1f = 0xC0
+
+sbox 0x20 = 0xB7
+sbox 0x21 = 0xFD
+sbox 0x22 = 0x93
+sbox 0x23 = 0x26
+sbox 0x24 = 0x36
+sbox 0x25 = 0x3F
+sbox 0x26 = 0xF7
+sbox 0x27 = 0xCC
+
+sbox 0x28 = 0x34
+sbox 0x29 = 0xA5
+sbox 0x2a = 0xE5
+sbox 0x2b = 0xF1
+sbox 0x2c = 0x71
+sbox 0x2d = 0xD8
+sbox 0x2e = 0x31
+sbox 0x2f = 0x15
+
+sbox 0x30 = 0x04
+sbox 0x31 = 0xC7
+sbox 0x32 = 0x23
+sbox 0x33 = 0xC3
+sbox 0x34 = 0x18
+sbox 0x35 = 0x96
+sbox 0x36 = 0x05
+sbox 0x37 = 0x9A
+
+sbox 0x38 = 0x07
+sbox 0x39 = 0x12
+sbox 0x3a = 0x80
+sbox 0x3b = 0xE2
+sbox 0x3c = 0xEB
+sbox 0x3d = 0x27
+sbox 0x3e = 0xB2
+sbox 0x3f = 0x75
+
+sbox 0x40 = 0x09
+sbox 0x41 = 0x83
+sbox 0x42 = 0x2C
+sbox 0x43 = 0x1A
+sbox 0x44 = 0x1B
+sbox 0x45 = 0x6E
+sbox 0x46 = 0x5A
+sbox 0x47 = 0xA0
+
+sbox 0x48 = 0x52
+sbox 0x49 = 0x3B
+sbox 0x4a = 0xD6
+sbox 0x4b = 0xB3
+sbox 0x4c = 0x29
+sbox 0x4d = 0xE3
+sbox 0x4e = 0x2F
+sbox 0x4f = 0x84
+
+sbox 0x50 = 0x53
+sbox 0x51 = 0xD1
+sbox 0x52 = 0x00
+sbox 0x53 = 0xED
+sbox 0x54 = 0x20
+sbox 0x55 = 0xFC
+sbox 0x56 = 0xB1
+sbox 0x57 = 0x5B
+
+sbox 0x58 = 0x6A
+sbox 0x59 = 0xCB
+sbox 0x5a = 0xBE
+sbox 0x5b = 0x39
+sbox 0x5c = 0x4A
+sbox 0x5d = 0x4C
+sbox 0x5e = 0x58
+sbox 0x5f = 0xCF
+
+sbox 0x60 = 0xD0
+sbox 0x61 = 0xEF
+sbox 0x62 = 0xAA
+sbox 0x63 = 0xFB
+sbox 0x64 = 0x43
+sbox 0x65 = 0x4D
+sbox 0x66 = 0x33
+sbox 0x67 = 0x85
+
+sbox 0x68 = 0x45
+sbox 0x69 = 0xF9
+sbox 0x6a = 0x02
+sbox 0x6b = 0x7F
+sbox 0x6c = 0x50
+sbox 0x6d = 0x3C
+sbox 0x6e = 0x9F
+sbox 0x6f = 0xA8
+
+sbox 0x70 = 0x51
+sbox 0x71 = 0xA3
+sbox 0x72 = 0x40
+sbox 0x73 = 0x8F
+sbox 0x74 = 0x92
+sbox 0x75 = 0x9D
+sbox 0x76 = 0x38
+sbox 0x77 = 0xF5
+
+sbox 0x78 = 0xBC
+sbox 0x79 = 0xB6
+sbox 0x7a = 0xDA
+sbox 0x7b = 0x21
+sbox 0x7c = 0x10
+sbox 0x7d = 0xFF
+sbox 0x7e = 0xF3
+sbox 0x7f = 0xD2
+
+sbox 0x80 = 0xCD
+sbox 0x81 = 0x0C
+sbox 0x82 = 0x13
+sbox 0x83 = 0xEC
+sbox 0x84 = 0x5F
+sbox 0x85 = 0x97
+sbox 0x86 = 0x44
+sbox 0x87 = 0x17
+
+sbox 0x88 = 0xC4
+sbox 0x89 = 0xA7
+sbox 0x8a = 0x7E
+sbox 0x8b = 0x3D
+sbox 0x8c = 0x64
+sbox 0x8d = 0x5D
+sbox 0x8e = 0x19
+sbox 0x8f = 0x73
+
+sbox 0x90 = 0x60
+sbox 0x91 = 0x81
+sbox 0x92 = 0x4F
+sbox 0x93 = 0xDC
+sbox 0x94 = 0x22
+sbox 0x95 = 0x2A
+sbox 0x96 = 0x90
+sbox 0x97 = 0x88
+
+sbox 0x98 = 0x46
+sbox 0x99 = 0xEE
+sbox 0x9a = 0xB8
+sbox 0x9b = 0x14
+sbox 0x9c = 0xDE
+sbox 0x9d = 0x5E
+sbox 0x9e = 0x0B
+sbox 0x9f = 0xDB
+
+sbox 0xa0 = 0xE0
+sbox 0xa1 = 0x32
+sbox 0xa2 = 0x3A
+sbox 0xa3 = 0x0A
+sbox 0xa4 = 0x49
+sbox 0xa5 = 0x06
+sbox 0xa6 = 0x24
+sbox 0xa7 = 0x5C
+
+sbox 0xa8 = 0xC2
+sbox 0xa9 = 0xD3
+sbox 0xaa = 0xAC
+sbox 0xab = 0x62
+sbox 0xac = 0x91
+sbox 0xad = 0x95
+sbox 0xae = 0xE4
+sbox 0xaf = 0x79
+
+sbox 0xb0 = 0xE7
+sbox 0xb1 = 0xC8
+sbox 0xb2 = 0x37
+sbox 0xb3 = 0x6D
+sbox 0xb4 = 0x8D
+sbox 0xb5 = 0xD5
+sbox 0xb6 = 0x4E
+sbox 0xb7 = 0xA9
+
+sbox 0xb8 = 0x6C
+sbox 0xb9 = 0x56
+sbox 0xba = 0xF4
+sbox 0xbb = 0xEA
+sbox 0xbc = 0x65
+sbox 0xbd = 0x7A
+sbox 0xbe = 0xAE
+sbox 0xbf = 0x08
+
+sbox 0xc0 = 0xBA
+sbox 0xc1 = 0x78
+sbox 0xc2 = 0x25
+sbox 0xc3 = 0x2E
+sbox 0xc4 = 0x1C
+sbox 0xc5 = 0xA6
+sbox 0xc6 = 0xB4
+sbox 0xc7 = 0xC6
+
+sbox 0xc8 = 0xE8
+sbox 0xc9 = 0xDD
+sbox 0xca = 0x74
+sbox 0xcb = 0x1F
+sbox 0xcc = 0x4B
+sbox 0xcd = 0xBD
+sbox 0xce = 0x8B
+sbox 0xcf = 0x8A
+
+sbox 0xd0 = 0x70
+sbox 0xd1 = 0x3E
+sbox 0xd2 = 0xB5
+sbox 0xd3 = 0x66
+sbox 0xd4 = 0x48
+sbox 0xd5 = 0x03
+sbox 0xd6 = 0xF6
+sbox 0xd7 = 0x0E
+
+sbox 0xd8 = 0x61
+sbox 0xd9 = 0x35
+sbox 0xda = 0x57
+sbox 0xdb = 0xB9
+sbox 0xdc = 0x86
+sbox 0xdd = 0xC1
+sbox 0xde = 0x1D
+sbox 0xdf = 0x9E
+
+sbox 0xe0 = 0xE1
+sbox 0xe1 = 0xF8
+sbox 0xe2 = 0x98
+sbox 0xe3 = 0x11
+sbox 0xe4 = 0x69
+sbox 0xe5 = 0xD9
+sbox 0xe6 = 0x8E
+sbox 0xe7 = 0x94
+
+sbox 0xe8 = 0x9B
+sbox 0xe9 = 0x1E
+sbox 0xea = 0x87
+sbox 0xeb = 0xE9
+sbox 0xec = 0xCE
+sbox 0xed = 0x55
+sbox 0xee = 0x28
+sbox 0xef = 0xDF
+
+sbox 0xf0 = 0x8C
+sbox 0xf1 = 0xA1
+sbox 0xf2 = 0x89
+sbox 0xf3 = 0x0D
+sbox 0xf4 = 0xBF
+sbox 0xf5 = 0xE6
+sbox 0xf6 = 0x42
+sbox 0xf7 = 0x68
+
+sbox 0xf8 = 0x41
+sbox 0xf9 = 0x99
+sbox 0xfa = 0x2D
+sbox 0xfb = 0x0F
+sbox 0xfc = 0xB0
+sbox 0xfd = 0x54
+sbox 0xfe = 0xBB
+sbox 0xff = 0x16
+
+{----}
+
+sboxRev 0x63 = 0x00
+sboxRev 0x7C = 0x01
+sboxRev 0x77 = 0x02
+sboxRev 0x7B = 0x03
+sboxRev 0xF2 = 0x04
+sboxRev 0x6B = 0x05
+sboxRev 0x6F = 0x06
+sboxRev 0xC5 = 0x07
+
+sboxRev 0x30 = 0x08
+sboxRev 0x01 = 0x09
+sboxRev 0x67 = 0x0a
+sboxRev 0x2B = 0x0b
+sboxRev 0xFE = 0x0c
+sboxRev 0xD7 = 0x0d
+sboxRev 0xAB = 0x0e
+sboxRev 0x76 = 0x0f
+
+sboxRev 0xCA = 0x10
+sboxRev 0x82 = 0x11
+sboxRev 0xC9 = 0x12
+sboxRev 0x7D = 0x13
+sboxRev 0xFA = 0x14
+sboxRev 0x59 = 0x15
+sboxRev 0x47 = 0x16
+sboxRev 0xF0 = 0x17
+
+sboxRev 0xAD = 0x18
+sboxRev 0xD4 = 0x19
+sboxRev 0xA2 = 0x1a
+sboxRev 0xAF = 0x1b
+sboxRev 0x9C = 0x1c
+sboxRev 0xA4 = 0x1d
+sboxRev 0x72 = 0x1e
+sboxRev 0xC0 = 0x1f
+
+sboxRev 0xB7 = 0x20
+sboxRev 0xFD = 0x21
+sboxRev 0x93 = 0x22
+sboxRev 0x26 = 0x23
+sboxRev 0x36 = 0x24
+sboxRev 0x3F = 0x25
+sboxRev 0xF7 = 0x26
+sboxRev 0xCC = 0x27
+
+sboxRev 0x34 = 0x28
+sboxRev 0xA5 = 0x29
+sboxRev 0xE5 = 0x2a
+sboxRev 0xF1 = 0x2b
+sboxRev 0x71 = 0x2c
+sboxRev 0xD8 = 0x2d
+sboxRev 0x31 = 0x2e
+sboxRev 0x15 = 0x2f
+
+sboxRev 0x04 = 0x30
+sboxRev 0xC7 = 0x31
+sboxRev 0x23 = 0x32
+sboxRev 0xC3 = 0x33
+sboxRev 0x18 = 0x34
+sboxRev 0x96 = 0x35
+sboxRev 0x05 = 0x36
+sboxRev 0x9A = 0x37
+
+sboxRev 0x07 = 0x38
+sboxRev 0x12 = 0x39
+sboxRev 0x80 = 0x3a
+sboxRev 0xE2 = 0x3b
+sboxRev 0xEB = 0x3c
+sboxRev 0x27 = 0x3d
+sboxRev 0xB2 = 0x3e
+sboxRev 0x75 = 0x3f
+
+sboxRev 0x09 = 0x40
+sboxRev 0x83 = 0x41
+sboxRev 0x2C = 0x42
+sboxRev 0x1A = 0x43
+sboxRev 0x1B = 0x44
+sboxRev 0x6E = 0x45
+sboxRev 0x5A = 0x46
+sboxRev 0xA0 = 0x47
+
+sboxRev 0x52 = 0x48
+sboxRev 0x3B = 0x49
+sboxRev 0xD6 = 0x4a
+sboxRev 0xB3 = 0x4b
+sboxRev 0x29 = 0x4c
+sboxRev 0xE3 = 0x4d
+sboxRev 0x2F = 0x4e
+sboxRev 0x84 = 0x4f
+
+sboxRev 0x53 = 0x50
+sboxRev 0xD1 = 0x51
+sboxRev 0x00 = 0x52
+sboxRev 0xED = 0x53
+sboxRev 0x20 = 0x54
+sboxRev 0xFC = 0x55
+sboxRev 0xB1 = 0x56
+sboxRev 0x5B = 0x57
+
+sboxRev 0x6A = 0x58
+sboxRev 0xCB = 0x59
+sboxRev 0xBE = 0x5a
+sboxRev 0x39 = 0x5b
+sboxRev 0x4A = 0x5c
+sboxRev 0x4C = 0x5d
+sboxRev 0x58 = 0x5e
+sboxRev 0xCF = 0x5f
+
+sboxRev 0xD0 = 0x60
+sboxRev 0xEF = 0x61
+sboxRev 0xAA = 0x62
+sboxRev 0xFB = 0x63
+sboxRev 0x43 = 0x64
+sboxRev 0x4D = 0x65
+sboxRev 0x33 = 0x66
+sboxRev 0x85 = 0x67
+
+sboxRev 0x45 = 0x68
+sboxRev 0xF9 = 0x69
+sboxRev 0x02 = 0x6a
+sboxRev 0x7F = 0x6b
+sboxRev 0x50 = 0x6c
+sboxRev 0x3C = 0x6d
+sboxRev 0x9F = 0x6e
+sboxRev 0xA8 = 0x6f
+
+sboxRev 0x51 = 0x70
+sboxRev 0xA3 = 0x71
+sboxRev 0x40 = 0x72
+sboxRev 0x8F = 0x73
+sboxRev 0x92 = 0x74
+sboxRev 0x9D = 0x75
+sboxRev 0x38 = 0x76
+sboxRev 0xF5 = 0x77
+
+sboxRev 0xBC = 0x78
+sboxRev 0xB6 = 0x79
+sboxRev 0xDA = 0x7a
+sboxRev 0x21 = 0x7b
+sboxRev 0x10 = 0x7c
+sboxRev 0xFF = 0x7d
+sboxRev 0xF3 = 0x7e
+sboxRev 0xD2 = 0x7f
+
+sboxRev 0xCD = 0x80
+sboxRev 0x0C = 0x81
+sboxRev 0x13 = 0x82
+sboxRev 0xEC = 0x83
+sboxRev 0x5F = 0x84
+sboxRev 0x97 = 0x85
+sboxRev 0x44 = 0x86
+sboxRev 0x17 = 0x87
+
+sboxRev 0xC4 = 0x88
+sboxRev 0xA7 = 0x89
+sboxRev 0x7E = 0x8a
+sboxRev 0x3D = 0x8b
+sboxRev 0x64 = 0x8c
+sboxRev 0x5D = 0x8d
+sboxRev 0x19 = 0x8e
+sboxRev 0x73 = 0x8f
+
+sboxRev 0x60 = 0x90
+sboxRev 0x81 = 0x91
+sboxRev 0x4F = 0x92
+sboxRev 0xDC = 0x93
+sboxRev 0x22 = 0x94
+sboxRev 0x2A = 0x95
+sboxRev 0x90 = 0x96
+sboxRev 0x88 = 0x97
+
+sboxRev 0x46 = 0x98
+sboxRev 0xEE = 0x99
+sboxRev 0xB8 = 0x9a
+sboxRev 0x14 = 0x9b
+sboxRev 0xDE = 0x9c
+sboxRev 0x5E = 0x9d
+sboxRev 0x0B = 0x9e
+sboxRev 0xDB = 0x9f
+
+sboxRev 0xE0 = 0xa0
+sboxRev 0x32 = 0xa1
+sboxRev 0x3A = 0xa2
+sboxRev 0x0A = 0xa3
+sboxRev 0x49 = 0xa4
+sboxRev 0x06 = 0xa5
+sboxRev 0x24 = 0xa6
+sboxRev 0x5C = 0xa7
+
+sboxRev 0xC2 = 0xa8
+sboxRev 0xD3 = 0xa9
+sboxRev 0xAC = 0xaa
+sboxRev 0x62 = 0xab
+sboxRev 0x91 = 0xac
+sboxRev 0x95 = 0xad
+sboxRev 0xE4 = 0xae
+sboxRev 0x79 = 0xaf
+
+sboxRev 0xE7 = 0xb0
+sboxRev 0xC8 = 0xb1
+sboxRev 0x37 = 0xb2
+sboxRev 0x6D = 0xb3
+sboxRev 0x8D = 0xb4
+sboxRev 0xD5 = 0xb5
+sboxRev 0x4E = 0xb6
+sboxRev 0xA9 = 0xb7
+
+sboxRev 0x6C = 0xb8
+sboxRev 0x56 = 0xb9
+sboxRev 0xF4 = 0xba
+sboxRev 0xEA = 0xbb
+sboxRev 0x65 = 0xbc
+sboxRev 0x7A = 0xbd
+sboxRev 0xAE = 0xbe
+sboxRev 0x08 = 0xbf
+
+sboxRev 0xBA = 0xc0
+sboxRev 0x78 = 0xc1
+sboxRev 0x25 = 0xc2
+sboxRev 0x2E = 0xc3
+sboxRev 0x1C = 0xc4
+sboxRev 0xA6 = 0xc5
+sboxRev 0xB4 = 0xc6
+sboxRev 0xC6 = 0xc7
+
+sboxRev 0xE8 = 0xc8
+sboxRev 0xDD = 0xc9
+sboxRev 0x74 = 0xca
+sboxRev 0x1F = 0xcb
+sboxRev 0x4B = 0xcc
+sboxRev 0xBD = 0xcd
+sboxRev 0x8B = 0xce
+sboxRev 0x8A = 0xcf
+
+sboxRev 0x70 = 0xd0
+sboxRev 0x3E = 0xd1
+sboxRev 0xB5 = 0xd2
+sboxRev 0x66 = 0xd3
+sboxRev 0x48 = 0xd4
+sboxRev 0x03 = 0xd5
+sboxRev 0xF6 = 0xd6
+sboxRev 0x0E = 0xd7
+
+sboxRev 0x61 = 0xd8
+sboxRev 0x35 = 0xd9
+sboxRev 0x57 = 0xda
+sboxRev 0xB9 = 0xdb
+sboxRev 0x86 = 0xdc
+sboxRev 0xC1 = 0xdd
+sboxRev 0x1D = 0xde
+sboxRev 0x9E = 0xdf
+
+sboxRev 0xE1 = 0xe0
+sboxRev 0xF8 = 0xe1
+sboxRev 0x98 = 0xe2
+sboxRev 0x11 = 0xe3
+sboxRev 0x69 = 0xe4
+sboxRev 0xD9 = 0xe5
+sboxRev 0x8E = 0xe6
+sboxRev 0x94 = 0xe7
+
+sboxRev 0x9B = 0xe8
+sboxRev 0x1E = 0xe9
+sboxRev 0x87 = 0xea
+sboxRev 0xE9 = 0xeb
+sboxRev 0xCE = 0xec
+sboxRev 0x55 = 0xed
+sboxRev 0x28 = 0xee
+sboxRev 0xDF = 0xef
+
+sboxRev 0x8C = 0xf0
+sboxRev 0xA1 = 0xf1
+sboxRev 0x89 = 0xf2
+sboxRev 0x0D = 0xf3
+sboxRev 0xBF = 0xf4
+sboxRev 0xE6 = 0xf5
+sboxRev 0x42 = 0xf6
+sboxRev 0x68 = 0xf7
+
+sboxRev 0x41 = 0xf8
+sboxRev 0x99 = 0xf9
+sboxRev 0x2D = 0xfa
+sboxRev 0x0F = 0xfb
+sboxRev 0xB0 = 0xfc
+sboxRev 0x54 = 0xfd
+sboxRev 0xBB = 0xfe
+sboxRev 0x16 = 0xff
+
+xtime :: Word32 -> Word32
+xtime x = b
+	where	a = x `shiftL` 1
+		b = if a .&. (0x0100) == 0 then a else a `xor` 0x11b
+
+xtimeX2 :: Word32 -> Word32
+--xtimeX2 = xtime . xtime
+xtimeX2 x = c
+	where	a = x `shiftL` 2
+		b = if a .&. (0x0200) == 0 then a else a `xor` 0x236
+		c = if b .&. (0x0100) == 0 then b else b `xor` 0x11b
+
+xtimeX3 :: Word32 -> Word32
+--xtimeX3 = xtime . xtime . xtime
+xtimeX3 x = d
+	where	a = x `shiftL` 3
+		b = if a .&. (0x0400) == 0 then a else a `xor` 0x46c
+		c = if b .&. (0x0200) == 0 then b else b `xor` 0x236
+		d = if c .&. (0x0100) == 0 then c else c `xor` 0x11b
+
+xtime03 :: Word32 -> Word32
+xtime03 x = x `xor` (xtime x)
+
+xtime0e :: Word32 -> Word32 
+xtime0e x = xtime (x `xor` (xtime (x `xor` (xtime x))))
+
+xtime09 :: Word32 -> Word32 
+xtime09 x = x `xor` (xtimeX3 x)
+
+xtime0d :: Word32 -> Word32 
+xtime0d x = x `xor` (xtimeX2 (x `xor` (xtime x)))
+
+xtime0b :: Word32 -> Word32 
+xtime0b x = x `xor` (xtime (x `xor` (xtimeX2 x)))
+
+generateKey :: Int -> Int -> Word32 -> Word32 -> Word32
+generateKey nk i wIminus1 wIminusNk = 
+		(temp' `xor` wIminusNk)
+	where temp' = 
+		if (i `mod` nk) == 0 then (subword(rotword temp)) `xor` rcon
+		else if (nk > 6) && ((i `mod` nk) == 4) then subword temp
+		else temp
+	      temp = wIminus1	
+	      subword :: Word32 -> Word32
+	      subword w = (a `shiftL` 24) .|. (b `shiftL` 16) .|.
+	      		  (c `shiftL` 8) .|. d
+			  where a = sbox ((w `shiftR` 24) .&. 0xff)
+			        b = sbox ((w `shiftR` 16) .&. 0xff)
+			        c = sbox ((w `shiftR`  8) .&. 0xff)
+			        d = sbox ( w             .&. 0xff)
+	      rotword :: Word32 -> Word32
+	      rotword w = w `rotateL` 8 			
+	      rcon :: Word32
+	      rcon = ((fromIntegral rconMSB)::Word32) `shiftL` 24
+	      rconMSB = (iterate xtime 0x01) !! ((i `div` nk) - 1)
+	
+wordify :: [Octet] -> [Word32]
+wordify [] = []
+wordify octets = firstWord:otherWords
+	where
+		(firstWord, otherOctets) = getWord32 octets
+		otherWords = wordify otherOctets
+
+generateKeys :: Int -> Int -> [Octet] -> [Word32]
+generateKeys nr nk mainKey = 
+		-- assert ((nk * 4) == length mainKey) $
+		(take (4 * (nr + 1)) xs)
+	where   
+		xs = (wordify mainKey) ++ (zipWith3 (generateKey nk)
+						(drop nk [0,1..])
+						(drop (nk - 1) xs)
+						xs
+					)
+
+subBytes :: State -> State
+subBytes (State (s00, s01, s02, s03)
+		(s10, s11, s12, s13)
+	 	(s20, s21, s22, s23)
+	 	(s30, s31, s32, s33)) = 
+	  State (sbox s00, sbox s01, sbox s02, sbox s03)
+ 		(sbox s10, sbox s11, sbox s12, sbox s13)
+		(sbox s20, sbox s21, sbox s22, sbox s23)
+		(sbox s30, sbox s31, sbox s32, sbox s33)
+
+subBytesRev :: State -> State
+subBytesRev (State (s00, s01, s02, s03)
+		   (s10, s11, s12, s13)
+	 	   (s20, s21, s22, s23)
+	 	   (s30, s31, s32, s33)) = 
+	  State (sboxRev s00, sboxRev s01, sboxRev s02, sboxRev s03)
+  		(sboxRev s10, sboxRev s11, sboxRev s12, sboxRev s13)
+  		(sboxRev s20, sboxRev s21, sboxRev s22, sboxRev s23)
+  		(sboxRev s30, sboxRev s31, sboxRev s32, sboxRev s33)
+
+shiftRows :: State -> State		
+shiftRows (State (s00, s01, s02, s03)
+		 (s10, s11, s12, s13)
+	 	 (s20, s21, s22, s23)
+	 	 (s30, s31, s32, s33)) = 
+	  State (s00, s01, s02, s03)
+ 		(s11, s12, s13, s10)
+		(s22, s23, s20, s21)
+		(s33, s30, s31, s32)
+
+shiftRowsRev :: State -> State		
+shiftRowsRev (State (s00, s01, s02, s03)
+		    (s10, s11, s12, s13)
+	 	    (s20, s21, s22, s23)
+	 	    (s30, s31, s32, s33)) = 
+	  State (s00, s01, s02, s03)
+ 		(s13, s10, s11, s12)
+		(s22, s23, s20, s21)
+		(s31, s32, s33, s30)
+
+mixColumn:: (Word32, Word32, Word32, Word32) -> (Word32, Word32, Word32, Word32)
+mixColumn (s0,s1,s2,s3) = 
+	((xtime   s0) `xor` (xtime03 s1) `xor`          s2  `xor`          s3 ,
+	          s0  `xor` (xtime   s1) `xor` (xtime03 s2) `xor`          s3 ,
+	          s0  `xor`          s1  `xor` (xtime   s2) `xor` (xtime03 s3),
+	 (xtime03 s0) `xor`          s1  `xor`          s2  `xor` (xtime   s3))
+
+mixColumns :: State -> State		
+mixColumns (State (s00, s01, s02, s03)
+		  (s10, s11, s12, s13)
+	 	  (s20, s21, s22, s23)
+	 	  (s30, s31, s32, s33)) = 
+	  State (r00, r01, r02, r03)
+ 		(r10, r11, r12, r13)
+		(r20, r21, r22, r23)
+		(r30, r31, r32, r33)
+	where (r00, r10, r20, r30) = mixColumn (s00, s10, s20, s30)
+	      (r01, r11, r21, r31) = mixColumn (s01, s11, s21, s31)
+	      (r02, r12, r22, r32) = mixColumn (s02, s12, s22, s32)
+	      (r03, r13, r23, r33) = mixColumn (s03, s13, s23, s33)
+
+mixColumnRev :: (Word32, Word32, Word32, Word32) 
+		-> (Word32, Word32, Word32, Word32)
+mixColumnRev (s0,s1,s2,s3) = 
+	((xtime0e s0) `xor` (xtime0b s1) `xor` (xtime0d s2) `xor` (xtime09 s3),
+	 (xtime09 s0) `xor` (xtime0e s1) `xor` (xtime0b s2) `xor` (xtime0d s3),
+	 (xtime0d s0) `xor` (xtime09 s1) `xor` (xtime0e s2) `xor` (xtime0b s3),
+	 (xtime0b s0) `xor` (xtime0d s1) `xor` (xtime09 s2) `xor` (xtime0e s3))
+
+mixColumnsRev :: State -> State		
+mixColumnsRev (State (s00, s01, s02, s03)
+		  (s10, s11, s12, s13)
+	 	  (s20, s21, s22, s23)
+	 	  (s30, s31, s32, s33)) = 
+	  State (r00, r01, r02, r03)
+ 		(r10, r11, r12, r13)
+		(r20, r21, r22, r23)
+		(r30, r31, r32, r33)
+	where (r00, r10, r20, r30) = mixColumnRev (s00, s10, s20, s30)
+	      (r01, r11, r21, r31) = mixColumnRev (s01, s11, s21, s31)
+	      (r02, r12, r22, r32) = mixColumnRev (s02, s12, s22, s32)
+	      (r03, r13, r23, r33) = mixColumnRev (s03, s13, s23, s33)
+
+addRoundKey :: State -> State -> State
+addRoundKey (State (k00, k01, k02, k03)
+		   (k10, k11, k12, k13)
+		   (k20, k21, k22, k23)
+	 	   (k30, k31, k32, k33))   
+	    (State (s00, s01, s02, s03)
+		   (s10, s11, s12, s13)
+		   (s20, s21, s22, s23)
+	 	   (s30, s31, s32, s33)) = 
+	  State (s00 `xor` k00, s01 `xor` k01, s02 `xor` k02, s03 `xor` k03)
+ 		(s10 `xor` k10, s11 `xor` k11, s12 `xor` k12, s13 `xor` k13)
+		(s20 `xor` k20, s21 `xor` k21, s22 `xor` k22, s23 `xor` k23)
+		(s30 `xor` k30, s31 `xor` k31, s32 `xor` k32, s33 `xor` k33)
+
+genAddRoundKey :: [Word32] -> [State -> State]
+genAddRoundKey [] = []
+genAddRoundKey (a:b:c:d:ks) = (addRoundKey k):(genAddRoundKey ks)
+	where k = State (fromIntegral s00, fromIntegral s01,
+			 fromIntegral s02, fromIntegral s03)
+			(fromIntegral s10, fromIntegral s11,
+			 fromIntegral s12, fromIntegral s13)
+			(fromIntegral s20, fromIntegral s21,
+			 fromIntegral s22, fromIntegral s23)
+			(fromIntegral s30, fromIntegral s31,
+			 fromIntegral s32, fromIntegral s33) 
+	      [s00, s10, s20, s30] = putWord32 a 		
+	      [s01, s11, s21, s31] = putWord32 b 		
+	      [s02, s12, s22, s32] = putWord32 c 		
+	      [s03, s13, s23, s33] = putWord32 d 		
+
+getWord32 :: [Octet] -> (Word32, [Octet])
+getWord32 (a:b:c:d:xs) = (x, xs)
+	where 
+		x = ((fromIntegral a) `shiftL` 24) .|. 
+		    ((fromIntegral b) `shiftL` 16) .|. 
+		    ((fromIntegral c) `shiftL`  8) .|. 
+		    ((fromIntegral d)            ) 
+
+putWord32 :: Word32 -> [Octet]
+--a bit slower putWord32 x = map fromIntegral [a,b,c,d]
+putWord32 x = [fromIntegral a, fromIntegral b, fromIntegral c, fromIntegral d]
+	where
+		a = (x `shiftR` 24) 
+		b = (x `shiftR` 16) .&. 255
+		c = (x `shiftR`  8) .&. 255
+		d = (x            ) .&. 255
+
+{-
+testGenerateKeys128 :: Test
+testGenerateKeys128 = 
+	let key = [0x2b, 0x7e, 0x15, 0x16,
+		   0x28, 0xae, 0xd2, 0xa6,
+		   0xab, 0xf7, 0x15, 0x88,
+		   0x09, 0xcf, 0x4f, 0x3c]
+	    expected = [0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c,
+	    		0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605,
+			0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f,
+			0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b,
+			0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00,
+			0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc,
+			0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd,
+			0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f,
+			0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f,
+			0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e,
+			0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6
+			]
+	in TestCase (do
+		assertEqual "" expected (generateKeys 10 4 key)
+	)
+
+
+testGenerateKeys192 :: Test
+testGenerateKeys192 = 
+	let key = [0x8e, 0x73, 0xb0, 0xf7,
+		   0xda, 0x0e, 0x64, 0x52,
+		   0xc8, 0x10, 0xf3, 0x2b,
+		   0x80, 0x90, 0x79, 0xe5,
+		   0x62, 0xf8, 0xea, 0xd2,
+		   0x52, 0x2c, 0x6b, 0x7b]
+	    expected = [0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5,
+	    		0x62f8ead2, 0x522c6b7b, 0xfe0c91f7, 0x2402f5a5,
+			0xec12068e, 0x6c827f6b, 0x0e7a95b9, 0x5c56fec2,
+			0x4db7b4bd, 0x69b54118, 0x85a74796, 0xe92538fd,
+			0xe75fad44, 0xbb095386, 0x485af057, 0x21efb14f
+			]
+	in TestCase (do
+		assertEqual "" expected
+			(take (length expected) (generateKeys 12 6 key))
+	)
+
+testGenerateKeys256 :: Test
+testGenerateKeys256 = 
+	let key = [0x60, 0x3d, 0xeb, 0x10,
+		   0x15, 0xca, 0x71, 0xbe,
+		   0x2b, 0x73, 0xae, 0xf0,
+		   0x85, 0x7d, 0x77, 0x81,
+		   0x1f, 0x35, 0x2c, 0x07,
+		   0x3b, 0x61, 0x08, 0xd7,
+		   0x2d, 0x98, 0x10, 0xa3,
+		   0x09, 0x14, 0xdf, 0xf4]
+	    expected = [0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781,
+	    		0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4,
+			0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde,
+			0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a,
+			0xd59aecb8, 0x5bf3c917, 0xfee94248, 0xde8ebe96
+			]
+	in TestCase (do
+		assertEqual "" expected 
+			(take (length expected) (generateKeys 14 8 key))
+	)
+
+testAes128 :: Test
+testAes128 = 
+	let key = [0x2b, 0x7e, 0x15, 0x16,
+		   0x28, 0xae, 0xd2, 0xa6,
+		   0xab, 0xf7, 0x15, 0x88,
+		   0x09, 0xcf, 0x4f, 0x3c]
+	    input = [0x32, 0x43, 0xf6, 0xa8, 
+	    	     0x88, 0x5a, 0x30, 0x8d,
+		     0x31, 0x31, 0x98, 0xa2,
+		     0xe0, 0x37, 0x07, 0x34]
+	    output = [0x39, 0x25, 0x84, 0x1d,
+	    	      0x02, 0xdc, 0x09, 0xfb,
+		      0xdc, 0x11, 0x85, 0x97,
+		      0x19, 0x6a, 0x0b, 0x32]
+	in TestCase (do
+		assertEqual "encrypt test" output (aes128Encrypt key input)
+		assertEqual "encrypt/decrypt test" input 
+				(aes128Decrypt key (aes128Encrypt key input))
+	)
+
+testAesRandom :: Test
+testAesRandom = 
+	TestCase (do
+		key128 <- getRandomOctets 16 
+		key192 <- getRandomOctets 24 
+		key256 <- getRandomOctets 32 
+		msg <- getRandomOctets 16 
+		assertEqual "aes128" msg 
+			(aes128Decrypt key128 (aes128Encrypt key128 msg))
+		assertEqual "aes192" msg 
+			(aes192Decrypt key192 (aes192Encrypt key192 msg))
+		assertEqual "aes256" msg 
+			(aes256Decrypt key256 (aes256Encrypt key256 msg))
+	)
+
+-- | HUnit tests
+tests :: Test
+tests = TestList [
+		TestLabel "testGenerateKeys128" testGenerateKeys128,
+		TestLabel "testGenerateKeys192" testGenerateKeys192,
+		TestLabel "testGenerateKeys256" testGenerateKeys256,
+		TestLabel "testAes128" testAes128,
+		TestLabel "testAesRandom" testAesRandom
+	]
+-}
+
+ Codec/Encryption/BurtonRNGSlow.hs view
@@ -0,0 +1,83 @@++{- | ++   This module includes two all-haskell implementations of Burton+   Smith's algorithm for a statistically-sound binary tree of random+   number generators.  See the following thread:++   <http://www.mail-archive.com/haskell-cafe@haskell.org/msg83901.html>++   Generally, Codec.Crypto.IntelAES should be used in favor of this+   module, but it is included for benchmarking purposes.++-}++module Codec.Encryption.BurtonRNGSlow+    (+     mkBurtonGen_reference,+     mkBurtonGen+     -- Plus, instances exported of course.+    )+where ++import System.Random (RandomGen, next, split)+import Crypto.Random.DRBG ()++import Codec.Encryption.AES (encrypt)+import Data.LargeWord++-- import Debug.Trace++--------------------------------------------------------------------------------+-- Reference implementation.++-- | Type of random number generators+--   This is a very simple but extremely inefficient vesion.+data RNG_ref = RNG_ref {-# UNPACK #-} !Word128 -- Seed+                       {-# UNPACK #-} !Word128 -- Counter+next128 (RNG_ref k c) = (encrypt k c, RNG_ref k (c+1))++-- | This instance is inefficient because it creates 128bits of+--   randomness but only uses an Int-sized (32 or 64 bit) subset of+--   them.+instance RandomGen RNG_ref where+  next g = (fromIntegral n, g')+   where (n,g') = next128 g+  split g@(RNG_ref k c) = (g', mkBurtonGen_reference n)+   where (n,g') = next128 g++-- | Extra slow reference implementation.+mkBurtonGen_reference :: Word128 -> RNG_ref+mkBurtonGen_reference seed = RNG_ref seed 0++--------------------------------------------------------------------------------+bits_in_int = round $ 1 + logBase 2 (fromIntegral (maxBound :: Int))+steps = 128 `quot` bits_in_int++-- | Type representing a more efficient random number generator that+-- | still uses an all-Haskell implementation.+data RNG = RNG {-# UNPACK #-} !Word128 -- Seed+               {-# UNPACK #-} !Word128 -- Last batch of random bits generated.+	       {-# UNPACK #-} !Word128 -- Counter+	       {-# UNPACK #-} !Int     -- Phase/step++-- | The idea with this one is that once we generate 128 bits of+--   randomness we parcel it out into two or four ints.+mkBurtonGen :: Word128 -> RNG+mkBurtonGen seed = RNG seed (encrypt seed 0) 1 0++next128' (RNG k _ c _) = RNG k (encrypt k c) (c+1) 0++instance RandomGen RNG where+  -- In this scenario its time to generate a new batch of bits:+  --  next g@(RNG k bits c s) | s == steps = next (next128' g)++-- FIXME: ASSUMES 64 BIT INTS  -- NONPORTABLE:+  -- This takes advantage the structure of the Word128 type:+  next g@(RNG k bits c 0) = (fromIntegral (loHalf bits), RNG k bits c 1)+  next g@(RNG k bits c 1) = (fromIntegral (hiHalf bits), next128' g)++  -- We waste some random bits here:+  split g@(RNG k bits c s) = (g', next128' g')+   where g' = next128' g+
+ Codec/Utils.hs view
@@ -0,0 +1,138 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Codec.Utils+-- Copyright   :  (c) Dominic Steinitz 2003+-- License     :  BSD-style (see the file ReadMe.tex)+-- +-- Maintainer  :  dominic.steinitz@blueyonder.co.uk+-- Stability   :  experimental+-- Portability :  portable+--+-- Utilities for coding and decoding.+--+-----------------------------------------------------------------------------++module Codec.Utils (+   -- * Types and Constants+   Octet,+   msb,+   -- * Octet Conversion Functions+   fromTwosComp, toTwosComp,+   toOctets, fromOctets,+   listFromOctets, listToOctets,+   i2osp+	      ) where++import Data.Word+import Data.Bits++powersOf n = 1 : (map (*n) (powersOf n))++toBase x = +   map fromIntegral .+   reverse .+   map (flip mod x) .+   takeWhile (/=0) .+   iterate (flip div x)++-- | Take a number a convert it to base n as a list of octets.++toOctets :: (Integral a, Integral b) => a -> b -> [Octet]+toOctets n x = (toBase n . fromIntegral) x++-- | This is used to (approximately) get back to a starting word list.+-- For example, if you have a list of 3 Word8 and try to convert them to+-- a Word32, the Word32 will get null-padded, and without correction, you+-- will get 4 Word8s when converting back. This corrects it.+-- Unfortunately, it also means you will have errors if trying to convert+-- Word8 lists with nulls on the end.+trimNulls :: [Word8] -> [Word8]+trimNulls = reverse . (dropWhile (== 0)) . reverse++-- | Converts a list of numbers into a list of octets.+-- The resultant list has nulls trimmed from the end to make this the dual+-- of listFromOctets (except when the original octet list ended with nulls;+-- see 'trimNulls').+listToOctets :: (Bits a, Integral a) => [a] -> [Octet]+listToOctets x = trimNulls $ concat paddedOctets where+    paddedOctets :: [[Octet]]+    paddedOctets = map (padTo bytes) rawOctets+    rawOctets :: [[Octet]]+    rawOctets = map (reverse . toOctets 256) x+    padTo :: Int -> [Octet] -> [Octet]+    padTo x y = take x $ y ++ repeat 0+    bytes :: Int+    bytes = bitSize (head x) `div` 8++-- | The basic type for encoding and decoding.++type Octet = Word8++-- | The most significant bit of an 'Octet'.++msb :: Int+msb = bitSize (undefined::Octet) - 1++-- | Take a list of octets (a number expressed in base n) and convert it+--   to a number.++fromOctets :: (Integral a, Integral b) => a -> [Octet] -> b+fromOctets n x = +   fromIntegral $ +   sum $ +   zipWith (*) (powersOf n) (reverse (map fromIntegral x))++-- | See 'listToOctets'.+listFromOctets :: (Integral a, Bits a) => [Octet] -> [a]+listFromOctets [] = []+listFromOctets x = result where+    result = first : rest+    first = fromOctets 256 first'+    first' = reverse $ take bytes x+    rest = listFromOctets $ drop bytes x+    bytes = bitSize first `div` 8++-- | Take the length of the required number of octets and convert the +--   number to base 256 padding it out to the required length. If the+--   required length is less than the number of octets of the converted+--   number then return the converted number. NB this is different from+--   the standard <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf>+--   but mimics how replicate behaves.++i2osp :: Integral a => Int -> a -> [Octet]+i2osp l y = +   pad ++ z+      where+         pad = replicate (l - unPaddedLen) (0x00::Octet)+	 z = toOctets 256 y+	 unPaddedLen = length z++-- | Convert from twos complement.++fromTwosComp :: Integral a => [Octet] -> a+fromTwosComp x =  conv x+   where conv []       = 0+         conv w@(x:xs) = if (testBit x msb)+                            then neg w+                            else pos w+         neg w@(x:xs)  = let z=(clearBit x msb):xs in+                            fromIntegral((fromOctets 256 z)-+                                         (128*(256^((length w)-1))))+         pos w         = fromIntegral(fromOctets 256 w)++toTwosComp :: Integral a => a -> [Octet]+toTwosComp x+   | x < 0     = reverse . plusOne . reverse . (map complement) $ u+   | x == 0    = [0x00]+   | otherwise = u+   where z@(y:ys) = toBase 256 (abs x)+         u        = if testBit y msb+                       then 0x00:z+                       else z++plusOne :: [Octet] -> [Octet]+plusOne [] = [1]+plusOne (x:xs) =+   if x == 0xff+      then 0x00:(plusOne xs)+      else (x+1):xs
+ Data/LargeWord.hs view
@@ -0,0 +1,153 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Data.LargeWord+-- Copyright   :  (c) Dominic Steinitz 2004+-- License     :  BSD-style (see the file ReadMe.tex)+-- +-- Maintainer  :  dominic.steinitz@blueyonder.co.uk+-- Stability   :  experimental+-- Portability :  portable+--+-- Provides Word128, Word192 and Word256 and a way of producing other+-- large words if required.+--+-----------------------------------------------------------------------------++module Data.LargeWord+   (LargeKey,Word96,Word128,Word160,Word192,Word224,Word256,+   loHalf, hiHalf) where++import Data.Word+import Data.Bits+import Numeric+import Data.Char++-- Keys have certain capabilities.++class LargeWord a where+   largeWordToInteger :: a -> Integer+   integerToLargeWord :: Integer -> a+   largeWordPlus :: a -> a -> a+   largeWordAnd :: a -> a -> a+   largeWordOr :: a -> a -> a+   largeWordShift :: a -> Int -> a+   largeWordXor :: a -> a -> a+   largeBitSize :: a -> Int++-- Word32 is a key in the obvious way.++instance LargeWord Word32 where+   largeWordToInteger = toInteger+   integerToLargeWord = fromInteger+   largeWordPlus = (+)+   largeWordAnd = (.&.)+   largeWordOr = (.|.)+   largeWordShift = shift+   largeWordXor = xor+   largeBitSize = bitSize++-- Word64 is a key in the obvious way.++instance LargeWord Word64 where+   largeWordToInteger = toInteger+   integerToLargeWord = fromInteger+   largeWordPlus = (+)+   largeWordAnd = (.&.)+   largeWordOr = (.|.)+   largeWordShift = shift+   largeWordXor = xor+   largeBitSize = bitSize++-- Define larger keys from smaller ones.++data LargeKey a b = LargeKey a b+   deriving (Eq, Ord)++{-# INLINE loHalf #-}+loHalf (LargeKey a b) = a+{-# INLINE hiHalf #-}+hiHalf (LargeKey a b) = b++instance (Ord a, Bits a, LargeWord a, Bits b, LargeWord b) =>+   LargeWord (LargeKey a b) where+      largeWordToInteger (LargeKey lo hi) =+         largeWordToInteger lo + (2^(bitSize lo)) * largeWordToInteger hi+      integerToLargeWord x =+         let (h,l) =  x `quotRem` (2^(bitSize lo))+             (lo,hi) = (integerToLargeWord l, integerToLargeWord h) in+                LargeKey lo hi+      largeWordPlus (LargeKey alo ahi) (LargeKey blo bhi) =+         LargeKey lo' hi' where+            lo' = alo + blo+            hi' = ahi + bhi + if lo' < alo then 1 else 0+      largeWordAnd (LargeKey alo ahi) (LargeKey blo bhi) =+         LargeKey lo' hi' where+            lo' = alo .&. blo+            hi' = ahi .&. bhi+      largeWordOr (LargeKey alo ahi) (LargeKey blo bhi) =+         LargeKey lo' hi' where+            lo' = alo .|. blo+            hi' = ahi .|. bhi+      largeWordXor (LargeKey alo ahi) (LargeKey blo bhi) =+         LargeKey lo' hi' where+            lo' = alo `xor` blo+            hi' = ahi `xor` bhi+      largeWordShift w 0 = w+      largeWordShift (LargeKey lo hi) x =+         if bitSize lo < bitSize hi+            then LargeKey (shift lo x) +                          (shift hi x .|. (shift (conv lo) (x - (bitSize lo))))+            else LargeKey (shift lo x)+                          (shift hi x .|. (conv $ shift lo (x - (bitSize lo))))+         where conv = integerToLargeWord . largeWordToInteger+      largeBitSize ~(LargeKey lo hi) = largeBitSize lo + largeBitSize hi++instance (Ord a, Bits a, LargeWord a, Bits b, LargeWord b) => Show (LargeKey a b) where+   showsPrec p = showInt . largeWordToInteger++instance (Ord a, Bits a, LargeWord a, Bits b, LargeWord b) => +   Num (LargeKey a b) where+      (+) = largeWordPlus+      fromInteger = integerToLargeWord ++-- Larger keys are instances of Bits provided their constituents are keys.++instance (Ord a, Bits a, LargeWord a, Bits b, LargeWord b) => +   Bits (LargeKey a b) where+      (.&.) = largeWordAnd+      (.|.) = largeWordOr+      xor = largeWordXor+      shift = largeWordShift+      bitSize = largeBitSize++instance (Ord a, Bits a, Bounded a, Integral a, LargeWord a, +                 Bits b, Bounded b, Integral b, LargeWord b) => +   Bounded (LargeKey a b) where+      minBound = 0+      maxBound =+         result where+            result =+               fromIntegral $+               (1 + fromIntegral (maxBound `asTypeOf` (boflk result)))*+                  (1 + fromIntegral (maxBound `asTypeOf` (aoflk result))) - 1++aoflk :: (LargeKey a b) -> a+aoflk = undefined+boflk :: (LargeKey a b) -> b+boflk = undefined++instance (Ord a, Bits a, LargeWord a, Ord b, Bits b, LargeWord b) =>+   Integral (LargeKey a b) where+      toInteger = largeWordToInteger++instance (Ord a, Bits a, LargeWord a, Ord b, Bits b, LargeWord b) =>+   Real (LargeKey a b)++instance Enum (LargeKey a b)++type Word96  = LargeKey Word32 Word64+type Word128 = LargeKey Word64 Word64+type Word160 = LargeKey Word32 Word128+type Word192 = LargeKey Word64 Word128+type Word224 = LargeKey Word32 Word192+type Word256 = LargeKey Word64 Word192
+ LICENSE view
@@ -0,0 +1,38 @@++The haskell source code in this package is licensed under a BSD3 license (listed below).++Note, right now this package also includes a copy of just a few files+from Dominic Steinitz's Crypto library.  This is hopefully temporary+-- a minor API change is the only reason for the duplication.+However, I verified that the included files ALSO have a BSD license.++-Ryan Newton+++BSD3 Full Text:+--------------------------------------------------------------------------------++Copyright (c) <year>, <copyright holder>+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:+    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.+    * 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.+    * Neither the name of the <organization> nor the+      names of its contributors may be used to endorse or promote products+      derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 <COPYRIGHT HOLDER> 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,157 @@+#!/usr/bin/env runhaskell+import Distribution.Simple++import Distribution.Simple.UserHooks+import Distribution.Simple.PreProcess+import Distribution.Simple.Setup+import Distribution.PackageDescription	+import Distribution.Simple.LocalBuildInfo	+import System.Cmd(system) +import System.Exit+import qualified System.Info as Info+import System.IO.Unsafe+import System.Directory+import Data.Maybe+import Data.List+import Data.IORef+import Debug.Trace++main = do+  putStrLn$ "  [intel-aes] Running Setup.hs..."++  defaultMainWithHooks $+   simpleUserHooks +    { postConf  = my_postConf+    , confHook  = my_conf+    , preBuild  = my_preBuild+    , buildHook = my_build+    , instHook  = my_install+    , cleanHook = my_clean+    }++-- A file will be our global variable:+tmpfile = ".temp.install_dir.txt"++--------------------------------------------------------------------------------+my_clean :: PackageDescription -> () -> UserHooks -> CleanFlags -> IO ()+my_clean desc () hooks flags = do +  putStrLn$ "\n  [intel-aes] Running external clean via Makefile"+  setCurrentDirectory "./cbits/"+  system "make clean"+  setCurrentDirectory ".."+  putStrLn$ "  [intel-aes] Done.  Now running normal cabal clean action.\n"+  (cleanHook simpleUserHooks) desc () hooks flags++--------------------------------------------------------------------------------+my_conf :: (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo+my_conf (gpd,hbi) flags = do +  (confHook simpleUserHooks) (gpd,hbi) flags++--------------------------------------------------------------------------------+-- we override postConf to keep it from complaining about a missing library:+my_postConf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()+my_postConf args conf desc localinfo = do+  let buildinfos = allBuildInfo desc+      desc2 = stripDesc desc+  putStrLn$ "  [intel-aes] Extra libraries initially: "++ show (map extraLibs buildinfos)+  putStrLn$ "  [intel-aes] Stripped extra libraries to: "++ show (map extraLibs $ allBuildInfo desc2)++  desc3 <- patchDesc desc2 localinfo+  -- Now call the default hook with a stripped down version:+  (postConf simpleUserHooks) args conf desc3 localinfo+++--------------------------------------------------------------------------------+-- Patch a package description for our quirky builda:+patchDesc desc localinfo = do+  let libd  = libdir$ absoluteInstallDirs desc localinfo NoCopyDest+  -- This is lame but I'm not sure how to get the same information at the preBuild step.+  -- writeIORef global_var_hack libd+  putStrLn$ "  [intel-aes] Determined install dir to be: " ++ show libd +  writeFile tmpfile libd+  putStrLn$ "  [intel-aes] Recorded install dir in " ++ show tmpfile+ +  root <- getCurrentDirectory+  -- Let's try a friendlier way to change the options:+  let Just lib = library desc+      lbi  = libBuildInfo lib +      oldO = ldOptions  lbi+      -- I'm not sure what the best policy is.  For now I'm adding+      -- BOTH the build dir and the eventual install dir...+      -- This will allow the package to function when it is built-but-not-installed.+      newO = ("-Wl,-rpath=" ++ libd) : +	     ("-Wl,-rpath=" ++ cbitsd) : +	     oldO+      cbitsd = root++"/cbits/"+      newlbi = lbi { ldOptions = newO +		   , extraLibDirs = cbitsd : extraLibDirs lbi }+      -- Whew... nested record updates are painful:+      desc3 = desc { library = Just (lib { libBuildInfo = newlbi})}++  putStrLn$ "  [intel-aes] Modified package info. " +  return desc3+++----------------------------------------+-- Strip out the special extra-libraries: entry+stripDesc desc = +       desc { library     = fmap stripLib (library desc) +  	    , executables = map  stripExe (executables desc)+	    }+stripLib lib = lib { libBuildInfo = stripBI (libBuildInfo lib) }+stripExe exe = exe { buildInfo = stripBI (buildInfo exe) }+stripBI bi   = bi  { extraLibs = filter filt (extraLibs bi) }++filt str = not (isInfixOf "intel_aes" str)++------------------------------------------------------------+my_preBuild :: Args -> BuildFlags -> IO HookedBuildInfo+my_preBuild args flags = do +  putStrLn$ "\n================================================================================"+  let +      ext = case Info.os of +	      "linux"   -> ".so"+	      "mac"     -> ".dylib"+	      "windows" -> ".dll"+	      _         -> error$ "Unexpected "+      cached_so = "./cbits/prebuilt/libintel_aes_"++ Info.os ++"_"++ Info.arch ++ ext+      dest = "./cbits/libintel_aes"++ext+  e <- doesFileExist cached_so+  if e then do +      putStrLn$ "  [intel-aes] Using prebuilt dynamic library: "++ cached_so+      copyFile cached_so dest+      putStrLn$ "  [intel-aes] Done copying into position: "++ dest+  else do     +      putStrLn$ "  [intel-aes] Running Makefile to build C/asm source..."+      rootdir <- getCurrentDirectory +      setCurrentDirectory "./cbits/"+      system "make"+      setCurrentDirectory rootdir+      putStrLn$ "  [intel-aes] Done with external build job."+  putStrLn$ "================================================================================\n"++  (preBuild simpleUserHooks) args flags++--------------------------------------------------------------------------------+my_build :: PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()+my_build desc linfo hooks flags = do +  putStrLn$ "  [intel-aes] Build action started."+  desc2 <- patchDesc desc linfo+  (buildHook simpleUserHooks) desc2 linfo hooks flags+  putStrLn$ "  [intel-aes] Build action finished.\n\n"++--------------------------------------------------------------------------------+my_install :: PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()+my_install desc linfo hooks flags = do +  putStrLn$ "  [intel-aes] Install action:"+  putStrLn$ "\n================================================================================"+  desc2 <- patchDesc desc linfo+  libd <- readFile tmpfile +  let dest = (libd ++ "/libintel_aes.so")+  putStrLn$ "  [intel-aes] Copying shared library to: " ++ show dest+  system$ "mkdir -p "++ libd -- NONPORTABLE+  copyFile "./cbits/libintel_aes.so" dest+  putStrLn$ "  [intel-aes] Done copying."+  -- removeFile tmpfile -- Might install more than once, right?+  putStrLn$ "================================================================================\n"+  (instHook simpleUserHooks) desc2 linfo hooks flags
+ SimpleRNGBench.hs view
@@ -0,0 +1,363 @@+#!/usr/bin/env runhaskell+{-# LANGUAGE BangPatterns, ScopedTypeVariables, ForeignFunctionInterface #-}+-- | A simple script to do some very basic timing of the RNGs.++--   It is important that we also run established stastical tests on+--   these RNGs a some point...++module Main where++import qualified Codec.Encryption.BurtonRNGSlow as BS++--import qualified Codec.Crypto.IntelAES.GladmanAES  as GA+import qualified Codec.Crypto.GladmanAES           as GA+import qualified Codec.Crypto.IntelAES.AESNI       as NI+import qualified Codec.Crypto.IntelAES             as IA+import qualified Codec.Crypto.ConvertRNG           as CR+-- import qualified Codec.Crypto.AES.Random        as Svein++import System.Exit (exitSuccess, exitFailure)+import System.Environment+import System.Random+import System.Posix    (sleep)+import System.CPUTime  (getCPUTime)+-- import Data.Time.Clock (diffUTCTime)+import System.CPUTime.Rdtsc+import System.Console.GetOpt++import GHC.Conc+import Control.Concurrent+import Control.Monad +import Control.Concurrent.Chan+import Control.Exception++import Crypto.Random (CryptoRandomGen(..))++import Data.IORef+import Data.List+import Data.Int+import Data.Word+import Data.List.Split+import Data.Serialize+import qualified Data.ByteString as B+import Text.Printf++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable (peek,poke)++import Benchmark.BinSearch++----------------------------------------------------------------------------------------------------+-- TEMP: MOVE ME ELSEWHERE:++mkAESGen_gladman :: Int -> CR.CRGtoRG (CR.BCtoCRG (GA.AES GA.N128))+mkAESGen_gladman int = CR.convertCRG gen+ where+  Right (gen :: CR.BCtoCRG (GA.AES GA.N128)) = newGen (B.append halfseed halfseed )+  halfseed = encode word64+  word64 = fromIntegral int :: Word64+++mkAESGen_gladman0 :: Int -> CR.CRGtoRG0 (CR.BCtoCRG (GA.AES GA.N128))+mkAESGen_gladman0 int = CR.CRGtoRG0 gen+ where+  Right (gen :: CR.BCtoCRG (GA.AES GA.N128)) = newGen (B.append halfseed halfseed )+  halfseed = encode word64+  word64 = fromIntegral int :: Word64+++----------------------------------------------------------------------------------------------------+-- Miscellaneous helpers:++-- I cannot *believe* there is not a standard call or an+-- easily-findable hackage library supporting locale-based printing of+-- numbers. [2011.01.28]+commaint :: Integral a => a -> String+commaint n = +   reverse $+   concat $+   intersperse "," $ +   chunk 3 $ +   reverse (show n)++padleft n str | length str >= n = str+padleft n str | otherwise       = take (n - length str) (repeat ' ') ++ str++padright n str | length str >= n = str+padright n str | otherwise       = str ++ take (n - length str) (repeat ' ')++fmt_num n = if n < 100 +	    then printf "%.2f" n+	    else commaint (round n)++-- WARNING! This is not actually good enough.  Even if we use forkOS+-- we would have to go further and pin the OS thread (e.g. in linux)+-- to keep the OS from waking up the process on a different core.+measure_freq :: IO Int64+measure_freq = do +   -- We measure the clock frequency on a bound thread.+   -- Otherwise we can get really screwy results from rdtsc if we+   -- migrate physical threads when we sleep or threadDelay.+   tmpchan <- newChan+   forkOS $ do +      t1 <- rdtsc+      -- sleep 1+      threadDelay (1000*1000)+      t2 <- rdtsc+      -- Just to be careful let's make sure this doesn't happen (this was how I found the problem before forkOS):+      when (t2 < t1) $ +        putStrLn$ "WARNING: rdtsc not monotonically increasing, first "++show t1++" then "++show t2++" on the same OS thread"+      writeChan tmpchan (if t2>t1 then t2-t1 else t1-t2)+   freq <- readChan tmpchan+   return (fromIntegral freq)++-- This version simply busy-waits to stay on the same core:+-- WOW! I'm STILL experiencing the non-monotonic rdtsc, even when not compiled with -threaded.+-- It can't be overflow can it?  The counter should be 64 bit...+--+-- UPDATE: [2011.01.28] This was a bug in the rdtsc package that dropping the precision to 32 bits.+measure_freq2 :: IO Int64+measure_freq2 = do +  let second = 1000 * 1000 * 1000 * 1000 -- picoseconds are annoying+  t1 <- rdtsc +  start <- getCPUTime+  let loop !n !last = +       do t2 <- rdtsc +	  when (t2 < last) $+	       putStrLn$ "COUNTERS WRAPPED "++ show (last,t2) +	  cput <- getCPUTime		+	  if (cput - start < second) +	   then loop (n+1) t2+	   else return (n,t2)+  (n,t2) <- loop 0 t1+  putStrLn$ "  Approx getCPUTime calls per second: "++ commaint n+  when (t2 < t1) $ +    putStrLn$ "WARNING: rdtsc not monotonically increasing, first "++show t1++" then "++show t2++" on the same OS thread"++  return$ fromIntegral (t2 - t1)++----------------------------------------------------------------------------------------------------+-- Drivers to get random numbers repeatedly.++incr !counter = +  do -- modifyIORef counter (+1)d+     -- Incrementing counter strictly (avoiding stack overflow) is annoying:+     c <- readIORef counter+     let c' = c+1+     evaluate c'+     writeIORef counter c'     ++loop :: RandomGen g => IORef Int -> (Int,g) -> IO b+loop !counter !(!n,!g) = +  do incr counter+--     putStr (show n); putChar ' '+     loop counter (next g)++data NoopRNG = NoopRNG+instance RandomGen NoopRNG where +  split g = (g,g)+  next g  = (0,g)++--foreign import ccall "cbits/c_test.c" blast_rands :: Ptr Int -> Ptr Int -> IO ()++type Kern = Int -> Ptr Int -> IO ()++-- [2011.01.28] Changing this to take "count" and "accumulator ptr" as arguments:+foreign import ccall "cbits/c_test.c" blast_rands :: Kern+foreign import ccall "cbits/c_test.c" store_loop  :: Kern+foreign import ccall unsafe "stdlib.hs" rand :: IO Int++loop2 :: IORef Int -> IO ()+loop2 !counter = +  do incr counter+     n <- rand+     loop2 counter +++----------------------------------------------------------------------------------------------------+-- Timing:++timeit numthreads freq msg mkgen =+  do +     counters <- forM [1..numthreads] (const$ newIORef 1) +     tids <- forM counters $ \counter -> +	        forkIO $ loop counter (next$ mkgen 23852358661234)   +     threadDelay (1000*1000) -- One second+     mapM_ killThread tids++     finals <- mapM readIORef counters+     let mean :: Double = fromIntegral (foldl1 (+) finals) / fromIntegral numthreads+         cycles_per :: Double = fromIntegral freq / mean+     print_result (round mean) msg cycles_per++print_result total msg cycles_per = +     putStrLn$ "    "++ padleft 11 (commaint total) ++" random ints generated "++ padright 27 ("["++msg++"]") ++" ~ "+	       ++ fmt_num cycles_per ++" cycles/int"+++-- FIXME: This isn't working yet because when the C call goes into a tight infinite loop killThread hangs...+-- KEEPING AROUND ONLY FOR FUTURE INVESTIGATION+------------------------------------------------------------+time_c :: Int -> Int64 -> (Ptr Int -> Ptr Int -> IO ()) -> IO Int+time_c numthreads freq ffn = do +  counter :: ForeignPtr Int <- mallocForeignPtr+  sum     :: ForeignPtr Int <- mallocForeignPtr+  tid <- forkOS $ +	 withForeignPtr counter $ \ cntr ->+	 withForeignPtr sum $ \ sm ->+          ffn cntr sm+  threadDelay (1000*1000) -- One second+  stat <- threadStatus tid+  putStrLn$ "Thread making foreign call's status: "++ show stat+  putStrLn$ "Killing thread running the foreign C call...\n"+  killThread tid -- This will hang!!!+  putStrLn$ "Killed.\n"+  total <- withForeignPtr counter peek +  putStrLn$ "Got total: " ++ show total+  return total+------------------------------------------------------------+++-- This version flips things around, and assume something about the+-- timing so that we can run a fixed number of randoms and time it.+-- (We could do binary search here.)+time_c2 :: Int -> Int64 -> String -> (Int -> Ptr Int -> IO ()) -> IO Int+time_c2 numthreads freq msg ffn = do +  ptr     :: ForeignPtr Int <- mallocForeignPtr++  let kern = if numthreads == 1+	     then ffn+	     else replicate_kernel numthreads ffn +      wrapped n = withForeignPtr ptr (kern$ fromIntegral n)+  (n,t) <- binSearch False 1 (1.0, 1.05) wrapped++  -- ONLY if we're in multi-threaded mode do we then run again with+  -- that input size on all threads:+----------------------------------------+-- NOTE, this approach is TOO SLOW.  For workloads that take a massive+-- parallel slowdown it doesn't make sense to use the same input size+-- in serial and in parallel.+-- DISABLING:+{-+  (n2,t2) <- +    if numthreads > 1 then do+      ptrs <- mapM (const mallocForeignPtr) [1..numthreads]+      tmpchan <- newChan+      putStrLn$ "       [forking threads for multithreaded measurement, input size "++ show n++"]"+      start <- getCPUTime+      tids <- forM ptrs $ \ptr -> forkIO $ +	       do withForeignPtr ptr (ffn$ fromIntegral n)+		  writeChan tmpchan ()     +      forM ptrs $ \_ -> readChan tmpchan+      end <- getCPUTime+      let t2 :: Double = fromIntegral (end-start) / 1000000000000.0+      putStrLn$ "       [joined threads, time "++ show t2 ++"]"+      return (n * fromIntegral numthreads, t2)+    else do +      return (n,t)+-}+----------------------------------------++  let total_per_second = round $ fromIntegral n * (1 / t)+      cycles_per = fromIntegral freq * t / fromIntegral n+  print_result total_per_second msg cycles_per+  return total_per_second++-- This lifts the C kernel to operate +replicate_kernel :: Int -> Kern -> Kern+replicate_kernel numthreads kern n ptr = do+  ptrs <- forM [1..numthreads]+	    (const mallocForeignPtr) +  tmpchan <- newChan+  -- let childwork = ceiling$ fromIntegral n / fromIntegral numthreads+  let childwork = n -- Keep it the same.. interested in per-thread throughput.+  -- Fork/join pattern:+  tids <- forM ptrs $ \ptr -> forkIO $ +	   withForeignPtr ptr $ \p -> do+	      kern (fromIntegral childwork) p+	      result <- peek p+	      writeChan tmpchan result++  results <- forM [1..numthreads] $ \_ -> +	       readChan tmpchan+  -- Meaningless semantics here... sum the child ptrs and write to the input one:+  poke ptr (foldl1 (+) results)+  return ()++----------------------------------------------------------------------------------------------------+-- Main Script++data Flag = NoC | Help | Test+  deriving (Show, Eq)++options = +   [ Option ['h']  ["help"]  (NoArg Help)  "print program help"+   , Option []     ["noC"]   (NoArg NoC)   "omit C benchmarks, haskell only"+   , Option ['t']  ["test"]  (NoArg Test)  "run some basic tests"+   ]++  +main = do +   argv <- getArgs+   let (opts,_,other) = getOpt Permute options argv++   when (Test `elem` opts)$ do+       IA.testIntelAES+       NI.testAESNI+       exitSuccess++   when (not$ null other) $ do+       putStrLn$ "ERROR: Unrecognized options: " +       mapM_ putStr other+       exitFailure++   when (Help `elem` opts) $ do+       putStr$ usageInfo "Benchmark random number generation" options+       exitSuccess++   putStrLn$ "\nHow many random numbers can we generate in a second on one thread?"++   t1 <- rdtsc+   t2 <- rdtsc+   putStrLn ("  Cost of rdtsc (ffi call):    " ++ show (t2 - t1))++   freq <- measure_freq2+   putStrLn$ "  Approx clock frequency:  " ++ commaint freq++--   svein <- Svein.newAESGen++   let gamut th = do+       putStrLn$ "  First, timing with System.Random interface:"+       timeit th freq "constant zero gen" (const NoopRNG)+       timeit th freq "System.Random stdGen" mkStdGen+       timeit th freq "PureHaskell/reference" BS.mkBurtonGen_reference+       timeit th freq "PureHaskell"           BS.mkBurtonGen+--       timeit th freq "Gladman inefficient"     GA.mkAESGen0+--       timeit th freq "Gladman"                 GA.mkAESGen+       timeit th freq "Gladman inefficient"     mkAESGen_gladman0+       timeit th freq "Gladman"                 mkAESGen_gladman+       timeit th freq "Compound gladman/intel"  IA.mkAESGen+--       timeit th freq "Svein's Gladman package" (const svein)+       timeit th freq "IntelAES inefficient"    NI.mkAESGen0+       timeit th freq "IntelAES"                NI.mkAESGen+++       when (not$ NoC `elem` opts) $ do+	  putStrLn$ "  Comparison to C's rand():"+	  time_c2 th freq "ptr store in C loop"   store_loop+	  time_c2 th freq "rand/store in C loop"  blast_rands+	  time_c2 th freq "rand in Haskell loop" (\n ptr -> forM_ [1..n]$ \_ -> rand )+	  time_c2 th freq "rand/store in Haskell loop"  (\n ptr -> forM_ [1..n]$ \_ -> do n <- rand; poke ptr n )+	  return ()+          -- timeit 1 freq "rand / Haskell loop" mkBurtonGen++   gamut 1++   when (numCapabilities > 1) $ do +--   when (False) $ do +       putStrLn$ "\nNow "++ show numCapabilities ++" threads, reporting mean randoms-per-second-per-thread:"+       gamut numCapabilities+       return ()++   putStrLn$ "Finished."
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/Makefile view
@@ -0,0 +1,48 @@++UNAME=$(shell uname -m)++# Must be 86 (for 32bit compiler) or 64 (for 64bit compiler)+ARCH=64+# Must be 32 or 64:+SZ=64++STATIC=lib/x$(ARCH)/libintel_aes.a+DYNAMIC=lib/x$(ARCH)/libintel_aes.so++SRC= src/intel_aes.c \+     asm/x$(ARCH)/iaesx$(ARCH).s \+     asm/x$(ARCH)/do_rdtsc.s++OBJ= obj/x$(ARCH)/intel_aes.o \+     obj/x$(ARCH)/iaesx$(ARCH).o \+     obj/x$(ARCH)/do_rdtsc.o++GCC=gcc+YASM=yasm+YASMFLAGS= -D__linux__ -g dwarf2 -f elf$(SZ) ++all: $(STATIC) $(DYNAMIC)+	cp lib/x$(ARCH)/* ../../++$(STATIC): $(OBJ)+	@mkdir -p lib/x$(ARCH)+	ar -r $@ $(OBJ)++$(DYNAMIC): $(OBJ)+	@mkdir -p lib/x$(ARCH)+	$(GCC) -shared -dynamic  -o $(DYNAMIC) $(OBJ)++obj/x$(ARCH)/do_rdtsc.o:  asm/x$(ARCH)/do_rdtsc.s+	@mkdir -p obj/x$(ARCH)+	$(YASM) $(YASMFLAGS) $< -o $@++obj/x$(ARCH)/iaesx$(ARCH).o:  asm/x$(ARCH)/iaesx$(ARCH).s+	@mkdir -p obj/x$(ARCH)+	$(YASM) $(YASMFLAGS) $< -o $@++obj/x$(ARCH)/intel_aes.o:  src/intel_aes.c+	@mkdir -p obj/x$(ARCH)+	$(GCC) -fPIC -O3 -g -Iinclude/ -c $< -o $@++clean:+	rm -f $(STATIC) $(DYNAMIC) $(OBJ)
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x64/do_rdtsc.s view
@@ -0,0 +1,37 @@+[bits 64]
+[CPU intelnop]
+
+; Copyright (c) 2010, Intel Corporation
+; All rights reserved.
+; 
+; Redistribution and use in source and binary forms, with or without 
+; modification, are permitted provided that the following conditions are met:
+; 
+;     * Redistributions of source code must retain the above copyright notice, 
+;       this list of conditions and the following disclaimer.
+;     * 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.
+;     * Neither the name of Intel Corporation nor the names of its contributors 
+;       may be used to endorse or promote products derived from this software 
+;       without specific prior written permission.
+; 
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+align 16
+global do_rdtsc
+do_rdtsc:
+
+	rdtsc
+	shl rdx, 32
+	or  rax, rdx
+	ret	0
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x64/iaesx64.s view
@@ -0,0 +1,2054 @@+[bits 64]
+[CPU intelnop]
+
+; Copyright (c) 2010, Intel Corporation
+; All rights reserved.
+; 
+; Redistribution and use in source and binary forms, with or without 
+; modification, are permitted provided that the following conditions are met:
+; 
+;     * Redistributions of source code must retain the above copyright notice, 
+;       this list of conditions and the following disclaimer.
+;     * 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.
+;     * Neither the name of Intel Corporation nor the names of its contributors 
+;       may be used to endorse or promote products derived from this software 
+;       without specific prior written permission.
+; 
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+%macro linux_setup 0
+%ifdef __linux__
+	mov rcx, rdi
+	mov rdx, rsi
+%endif
+%endmacro
+
+%macro inversekey 1
+	movdqu  xmm1,%1
+	aesimc	xmm0,xmm1
+	movdqu	%1,xmm0
+%endmacro
+
+%macro aesdeclast1 1
+	aesdeclast	xmm0,%1
+%endmacro
+
+%macro aesenclast1 1
+	aesenclast	xmm0,%1
+%endmacro
+
+%macro aesdec1 1
+	aesdec	xmm0,%1
+%endmacro
+
+%macro aesenc1 1
+	aesenc	xmm0,%1
+%endmacro
+
+
+%macro aesdeclast1_u 1
+	movdqu xmm4,%1
+	aesdeclast	xmm0,xmm4
+%endmacro
+
+%macro aesenclast1_u 1
+	movdqu xmm4,%1
+	aesenclast	xmm0,xmm4
+%endmacro
+
+%macro aesdec1_u 1
+	movdqu xmm4,%1
+	aesdec	xmm0,xmm4
+%endmacro
+
+%macro aesenc1_u 1
+	movdqu xmm4,%1
+	aesenc	xmm0,xmm4
+%endmacro
+ 
+%macro aesdec4 1
+	movdqa	xmm4,%1
+
+	aesdec	xmm0,xmm4
+	aesdec	xmm1,xmm4
+	aesdec	xmm2,xmm4
+	aesdec	xmm3,xmm4
+
+%endmacro
+
+%macro aesdeclast4 1
+	movdqa	xmm4,%1
+
+	aesdeclast	xmm0,xmm4
+	aesdeclast	xmm1,xmm4
+	aesdeclast	xmm2,xmm4
+	aesdeclast	xmm3,xmm4
+
+%endmacro
+
+
+%macro aesenc4 1
+	movdqa	xmm4,%1
+
+	aesenc	xmm0,xmm4
+	aesenc	xmm1,xmm4
+	aesenc	xmm2,xmm4
+	aesenc	xmm3,xmm4
+
+%endmacro
+
+%macro aesenclast4 1
+	movdqa	xmm4,%1
+
+	aesenclast	xmm0,xmm4
+	aesenclast	xmm1,xmm4
+	aesenclast	xmm2,xmm4
+	aesenclast	xmm3,xmm4
+
+%endmacro
+
+
+%macro load_and_inc4 1
+	movdqa	xmm4,%1
+	movdqa	xmm0,xmm5
+	movdqa  xmm1,xmm5
+	paddq	xmm1,[counter_add_one wrt rip]
+	movdqa  xmm2,xmm5
+	paddq	xmm2,[counter_add_two wrt rip]
+	movdqa  xmm3,xmm5
+	paddq	xmm3,[counter_add_three wrt rip]
+	pxor	xmm0,xmm4
+	paddq	xmm5,[counter_add_four wrt rip]
+	pxor	xmm1,xmm4
+	pxor	xmm2,xmm4
+	pxor	xmm3,xmm4
+%endmacro
+
+%macro xor_with_input4 1
+	movdqu xmm4,[%1]
+	pxor xmm0,xmm4
+	movdqu xmm4,[%1+16]
+	pxor xmm1,xmm4
+	movdqu xmm4,[%1+32]
+	pxor xmm2,xmm4
+	movdqu xmm4,[%1+48]
+	pxor xmm3,xmm4
+%endmacro
+
+
+
+%macro load_and_xor4 2
+	movdqa	xmm4,%2
+	movdqu	xmm0,[%1 + 0*16]
+	pxor	xmm0,xmm4
+	movdqu	xmm1,[%1 + 1*16]
+	pxor	xmm1,xmm4
+	movdqu	xmm2,[%1 + 2*16]
+	pxor	xmm2,xmm4
+	movdqu	xmm3,[%1 + 3*16]
+	pxor	xmm3,xmm4
+%endmacro
+
+%macro store4 1
+	movdqu [%1 + 0*16],xmm0
+	movdqu [%1 + 1*16],xmm1
+	movdqu [%1 + 2*16],xmm2
+	movdqu [%1 + 3*16],xmm3
+%endmacro
+
+%macro copy_round_keys 3
+	movdqu xmm4,[%2 + ((%3)*16)]
+	movdqa [%1 + ((%3)*16)],xmm4
+%endmacro
+
+
+%macro key_expansion_1_192 1
+		;; Assumes the xmm3 includes all zeros at this point. 
+        pshufd xmm2, xmm2, 11111111b        
+        shufps xmm3, xmm1, 00010000b        
+        pxor xmm1, xmm3        
+        shufps xmm3, xmm1, 10001100b
+        pxor xmm1, xmm3        
+		pxor xmm1, xmm2		
+		movdqu [rdx+%1], xmm1			
+%endmacro
+
+; Calculate w10 and w11 using calculated w9 and known w4-w5
+%macro key_expansion_2_192 1				
+		movdqa xmm5, xmm4
+		pslldq xmm5, 4
+		shufps xmm6, xmm1, 11110000b
+		pxor xmm6, xmm5
+		pxor xmm4, xmm6
+		pshufd xmm7, xmm4, 00001110b 
+		movdqu [rdx+%1], xmm7
+%endmacro
+
+
+section .data
+align 16
+shuffle_mask:
+DD 0FFFFFFFFh
+DD 03020100h
+DD 07060504h
+DD 0B0A0908h
+
+
+align 16
+counter_add_one:
+DD 1
+DD 0
+DD 0
+DD 0
+
+counter_add_two:
+DD 2
+DD 0
+DD 0
+DD 0
+
+counter_add_three:
+DD 3
+DD 0
+DD 0
+DD 0
+
+counter_add_four:
+DD 4
+DD 0
+DD 0
+DD 0
+
+
+
+section .text
+
+align 16
+key_expansion256:
+
+    pshufd xmm2, xmm2, 011111111b
+
+    movdqa xmm4, xmm1
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pxor xmm1, xmm2
+
+    movdqu [rdx], xmm1
+    add rdx, 0x10
+    
+    aeskeygenassist xmm4, xmm1, 0
+    pshufd xmm2, xmm4, 010101010b
+
+    movdqa xmm4, xmm3
+    pshufb xmm4, xmm5
+    pxor xmm3, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm3, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm3, xmm4
+    pxor xmm3, xmm2
+
+    movdqu [rdx], xmm3
+    add rdx, 0x10
+
+    ret
+
+
+
+align 16
+key_expansion128: 
+    pshufd xmm2, xmm2, 0xFF;
+    movdqa xmm3, xmm1
+    pshufb xmm3, xmm5
+    pxor xmm1, xmm3
+    pshufb xmm3, xmm5
+    pxor xmm1, xmm3
+    pshufb xmm3, xmm5
+    pxor xmm1, xmm3
+    pxor xmm1, xmm2
+
+    ; storing the result in the key schedule array
+    movdqu [rdx], xmm1
+    add rdx, 0x10                    
+    ret
+
+
+
+
+
+
+align 16
+global iEncExpandKey128
+iEncExpandKey128:
+
+		linux_setup
+
+        movdqu xmm1, [rcx]    ; loading the key
+
+        movdqu [rdx], xmm1
+
+        movdqa xmm5, [shuffle_mask wrt rip]
+
+        add rdx,16
+
+        aeskeygenassist xmm2, xmm1, 0x1     ; Generating round key 1
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x2     ; Generating round key 2
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x4     ; Generating round key 3
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x8     ; Generating round key 4
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x10    ; Generating round key 5
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x20    ; Generating round key 6
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x40    ; Generating round key 7
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x80    ; Generating round key 8
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x1b    ; Generating round key 9
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x36    ; Generating round key 10
+        call key_expansion128
+
+		ret 
+
+
+
+align 16
+global iEncExpandKey192
+iEncExpandKey192:
+
+		linux_setup
+		sub rsp,64+8
+		movdqa	[rsp],xmm6
+		movdqa	[rsp+16],xmm7
+
+
+        movq xmm7, [rcx+16]	; loading the AES key
+        movq [rdx+16], xmm7  ; Storing key in memory where all key expansion 
+        pshufd xmm4, xmm7, 01001111b
+        movdqu xmm1, [rcx]	; loading the AES key
+        movdqu [rdx], xmm1  ; Storing key in memory where all key expansion 
+			
+        pxor xmm3, xmm3		; Set xmm3 to be all zeros. Required for the key_expansion. 
+        pxor xmm6, xmm6		; Set xmm3 to be all zeros. Required for the key_expansion. 
+
+        aeskeygenassist xmm2, xmm4, 0x1     ; Complete round key 1 and generate round key 2 
+        key_expansion_1_192 24
+		key_expansion_2_192 40				
+
+        aeskeygenassist xmm2, xmm4, 0x2     ; Generate round key 3 and part of round key 4
+        key_expansion_1_192 48
+		key_expansion_2_192 64				
+
+        aeskeygenassist xmm2, xmm4, 0x4     ; Complete round key 4 and generate round key 5
+        key_expansion_1_192 72
+		key_expansion_2_192 88
+		
+        aeskeygenassist xmm2, xmm4, 0x8     ; Generate round key 6 and part of round key 7
+        key_expansion_1_192 96
+		key_expansion_2_192 112
+		
+        aeskeygenassist xmm2, xmm4, 0x10     ; Complete round key 7 and generate round key 8 
+        key_expansion_1_192 120
+		key_expansion_2_192 136				
+
+        aeskeygenassist xmm2, xmm4, 0x20     ; Generate round key 9 and part of round key 10
+        key_expansion_1_192 144
+		key_expansion_2_192 160				
+
+        aeskeygenassist xmm2, xmm4, 0x40     ; Complete round key 10 and generate round key 11
+        key_expansion_1_192 168
+		key_expansion_2_192 184				
+
+        aeskeygenassist xmm2, xmm4, 0x80     ; Generate round key 12
+        key_expansion_1_192 192
+
+
+		movdqa	xmm6,[rsp]
+		movdqa	xmm7,[rsp+16]
+		add rsp,64+8
+
+		ret 
+
+
+
+
+align 16
+global iDecExpandKey128
+iDecExpandKey128:
+
+	linux_setup
+	push rcx
+	push rdx
+	sub rsp,16+8
+
+	call iEncExpandKey128
+
+	add rsp,16+8
+	pop rdx
+	pop rcx
+
+	inversekey [rdx + 1*16]
+	inversekey [rdx + 2*16]
+	inversekey [rdx + 3*16]
+	inversekey [rdx + 4*16]
+	inversekey [rdx + 5*16]
+	inversekey [rdx + 6*16]
+	inversekey [rdx + 7*16]
+	inversekey [rdx + 8*16]
+	inversekey [rdx + 9*16]
+
+	ret
+
+
+align 16
+global iDecExpandKey192
+iDecExpandKey192:
+
+	linux_setup
+	push rcx
+	push rdx
+	sub rsp,16+8
+
+	call iEncExpandKey192
+
+	add rsp,16+8
+	pop rdx
+	pop rcx
+
+	
+	inversekey [rdx + 1*16]
+	inversekey [rdx + 2*16]
+	inversekey [rdx + 3*16]
+	inversekey [rdx + 4*16]
+	inversekey [rdx + 5*16]
+	inversekey [rdx + 6*16]
+	inversekey [rdx + 7*16]
+	inversekey [rdx + 8*16]
+	inversekey [rdx + 9*16]
+	inversekey [rdx + 10*16]
+	inversekey [rdx + 11*16]
+
+	ret
+
+
+
+align 16
+global iDecExpandKey256
+iDecExpandKey256:
+
+	linux_setup
+	push rcx
+	push rdx
+	sub rsp,16+8
+
+	call iEncExpandKey256
+
+	add rsp,16+8
+	pop rdx
+	pop rcx
+
+	inversekey [rdx + 1*16]
+	inversekey [rdx + 2*16]
+	inversekey [rdx + 3*16]
+	inversekey [rdx + 4*16]
+	inversekey [rdx + 5*16]
+	inversekey [rdx + 6*16]
+	inversekey [rdx + 7*16]
+	inversekey [rdx + 8*16]
+	inversekey [rdx + 9*16]
+	inversekey [rdx + 10*16]
+	inversekey [rdx + 11*16]
+	inversekey [rdx + 12*16]
+	inversekey [rdx + 13*16]
+
+	ret
+	
+
+	
+	
+align 16
+global iEncExpandKey256
+iEncExpandKey256:
+
+	linux_setup
+
+    movdqu xmm1, [rcx]    ; loading the key
+    movdqu xmm3, [rcx+16]
+    movdqu [rdx], xmm1  ; Storing key in memory where all key schedule will be stored
+    movdqu [rdx+16], xmm3 
+    
+    add rdx,32
+
+    movdqa xmm5, [shuffle_mask wrt rip]  ; this mask is used by key_expansion
+
+    aeskeygenassist xmm2, xmm3, 0x1     ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x2     ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x4     ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x8     ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x10    ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x20    ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x40    ; 
+;    call key_expansion256 
+
+    pshufd xmm2, xmm2, 011111111b
+
+    movdqa xmm4, xmm1
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pxor xmm1, xmm2
+
+    movdqu [rdx], xmm1
+
+
+	ret 
+	
+	
+	
+
+
+
+align 16
+global iDec128
+iDec128:
+
+	linux_setup
+	sub rsp,16*16+8
+
+
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+	test eax,eax
+	jz end_dec128
+
+	cmp eax,4
+	jl	lp128decsingle
+
+	test	rcx,0xf
+	jz		lp128decfour
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	mov rcx,rsp	
+	
+	
+
+align 16
+lp128decfour:
+	
+	test eax,eax
+	jz end_dec128
+
+	cmp eax,4
+	jl	lp128decsingle
+
+	load_and_xor4 rdx, [rcx+10*16]
+	add rdx,16*4
+	aesdec4 [rcx+9*16]
+	aesdec4 [rcx+8*16]
+	aesdec4 [rcx+7*16]
+	aesdec4 [rcx+6*16]
+	aesdec4 [rcx+5*16]
+	aesdec4 [rcx+4*16]
+	aesdec4 [rcx+3*16]
+	aesdec4 [rcx+2*16]
+	aesdec4 [rcx+1*16]
+	aesdeclast4 [rcx+0*16]
+	
+	sub eax,4
+	store4 r8+rdx-(16*4)
+	jmp lp128decfour
+
+
+	align 16
+lp128decsingle:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4,[rcx+10*16]
+	pxor xmm0, xmm4
+	aesdec1_u [rcx+9*16]
+	aesdec1_u [rcx+8*16]
+	aesdec1_u [rcx+7*16]
+	aesdec1_u [rcx+6*16]
+	aesdec1_u [rcx+5*16]
+	aesdec1_u [rcx+4*16]
+	aesdec1_u [rcx+3*16]
+	aesdec1_u [rcx+2*16]
+	aesdec1_u [rcx+1*16]
+	aesdeclast1_u [rcx+0*16]
+
+	add rdx, 16
+	movdqu  [r8 + rdx - 16], xmm0
+	dec eax
+	jnz lp128decsingle
+
+end_dec128:
+
+	add rsp,16*16+8
+	ret
+
+
+align 16
+global iDec128_CBC
+iDec128_CBC:
+	
+	linux_setup
+	sub rsp,16*16+8
+
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu	xmm5,[rax]
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	
+	sub r8,rdx
+
+
+	test eax,eax
+	jz end_dec128_CBC
+
+	cmp eax,4
+	jl	lp128decsingle_CBC
+
+	test	rcx,0xf
+	jz		lp128decfour_CBC
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	mov rcx,rsp	
+
+
+align 16
+lp128decfour_CBC:
+	
+	test eax,eax
+	jz end_dec128_CBC
+
+	cmp eax,4
+	jl	lp128decsingle_CBC
+
+	load_and_xor4 rdx, [rcx+10*16]
+	add rdx,16*4
+	aesdec4 [rcx+9*16]
+	aesdec4 [rcx+8*16]
+	aesdec4 [rcx+7*16]
+	aesdec4 [rcx+6*16]
+	aesdec4 [rcx+5*16]
+	aesdec4 [rcx+4*16]
+	aesdec4 [rcx+3*16]
+	aesdec4 [rcx+2*16]
+	aesdec4 [rcx+1*16]
+	aesdeclast4 [rcx+0*16]
+
+	pxor	xmm0,xmm5
+	movdqu	xmm4,[rdx - 16*4 + 0*16]
+	pxor	xmm1,xmm4
+	movdqu	xmm4,[rdx - 16*4 + 1*16]
+	pxor	xmm2,xmm4
+	movdqu	xmm4,[rdx - 16*4 + 2*16]
+	pxor	xmm3,xmm4
+	movdqu	xmm5,[rdx - 16*4 + 3*16]
+	
+	sub eax,4
+	store4 r8+rdx-(16*4)
+	jmp lp128decfour_CBC
+
+
+	align 16
+lp128decsingle_CBC:
+
+	movdqu xmm0, [rdx]
+	movdqa	xmm1,xmm0
+	movdqu xmm4,[rcx+10*16]
+	pxor xmm0, xmm4
+	aesdec1_u [rcx+9*16]
+	aesdec1_u [rcx+8*16]
+	aesdec1_u [rcx+7*16]
+	aesdec1_u [rcx+6*16]
+	aesdec1_u [rcx+5*16]
+	aesdec1_u [rcx+4*16]
+	aesdec1_u [rcx+3*16]
+	aesdec1_u [rcx+2*16]
+	aesdec1_u [rcx+1*16]
+	aesdeclast1_u [rcx+0*16]
+
+	pxor	xmm0,xmm5
+	movdqa	xmm5,xmm1
+	add rdx, 16
+	movdqu  [r8 + rdx - 16], xmm0
+	dec eax
+	jnz lp128decsingle_CBC
+
+end_dec128_CBC:
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm5
+	add rsp,16*16+8
+	ret
+
+
+align 16
+global iDec192_CBC
+iDec192_CBC:
+
+	linux_setup
+	sub rsp,16*16+8
+
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu	xmm5,[rax]
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	
+	sub r8,rdx
+
+	test eax,eax
+	jz end_dec192_CBC
+
+	cmp eax,4
+	jl	lp192decsingle_CBC
+
+	test	rcx,0xf
+	jz		lp192decfour_CBC
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	mov rcx,rsp	
+
+
+align 16
+lp192decfour_CBC:
+	
+	test eax,eax
+	jz end_dec192_CBC
+
+	cmp eax,4
+	jl	lp192decsingle_CBC
+
+	load_and_xor4 rdx, [rcx+12*16]
+	add rdx,16*4
+	aesdec4 [rcx+11*16]
+	aesdec4 [rcx+10*16]
+	aesdec4 [rcx+9*16]
+	aesdec4 [rcx+8*16]
+	aesdec4 [rcx+7*16]
+	aesdec4 [rcx+6*16]
+	aesdec4 [rcx+5*16]
+	aesdec4 [rcx+4*16]
+	aesdec4 [rcx+3*16]
+	aesdec4 [rcx+2*16]
+	aesdec4 [rcx+1*16]
+	aesdeclast4 [rcx+0*16]
+
+	pxor	xmm0,xmm5
+	movdqu	xmm4,[rdx - 16*4 + 0*16]
+	pxor	xmm1,xmm4
+	movdqu	xmm4,[rdx - 16*4 + 1*16]
+	pxor	xmm2,xmm4
+	movdqu	xmm4,[rdx - 16*4 + 2*16]
+	pxor	xmm3,xmm4
+	movdqu	xmm5,[rdx - 16*4 + 3*16]
+	
+	sub eax,4
+	store4 r8+rdx-(16*4)
+	jmp lp192decfour_CBC
+
+
+	align 16
+lp192decsingle_CBC:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4,[rcx+12*16]
+	movdqa	xmm1,xmm0
+	pxor xmm0, xmm4
+	aesdec1_u [rcx+11*16]
+	aesdec1_u [rcx+10*16]
+	aesdec1_u [rcx+9*16]
+	aesdec1_u [rcx+8*16]
+	aesdec1_u [rcx+7*16]
+	aesdec1_u [rcx+6*16]
+	aesdec1_u [rcx+5*16]
+	aesdec1_u [rcx+4*16]
+	aesdec1_u [rcx+3*16]
+	aesdec1_u [rcx+2*16]
+	aesdec1_u [rcx+1*16]
+	aesdeclast1_u [rcx+0*16]
+
+	pxor	xmm0,xmm5
+	movdqa	xmm5,xmm1
+	add rdx, 16
+	movdqu  [r8 + rdx - 16], xmm0
+	dec eax
+	jnz lp192decsingle_CBC
+
+end_dec192_CBC:
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm5
+	add rsp,16*16+8
+	ret
+
+
+
+
+align 16
+global iDec256_CBC
+iDec256_CBC:
+
+	linux_setup
+	sub rsp,16*16+8
+
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu	xmm5,[rax]
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	
+	sub r8,rdx
+
+	test eax,eax
+	jz end_dec256_CBC
+
+	cmp eax,4
+	jl	lp256decsingle_CBC
+
+	test	rcx,0xf
+	jz		lp256decfour_CBC
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	copy_round_keys rsp,rcx,13
+	copy_round_keys rsp,rcx,14
+	mov rcx,rsp	
+
+align 16
+lp256decfour_CBC:
+	
+	test eax,eax
+	jz end_dec256_CBC
+
+	cmp eax,4
+	jl	lp256decsingle_CBC
+
+	load_and_xor4 rdx, [rcx+14*16]
+	add rdx,16*4
+	aesdec4 [rcx+13*16]
+	aesdec4 [rcx+12*16]
+	aesdec4 [rcx+11*16]
+	aesdec4 [rcx+10*16]
+	aesdec4 [rcx+9*16]
+	aesdec4 [rcx+8*16]
+	aesdec4 [rcx+7*16]
+	aesdec4 [rcx+6*16]
+	aesdec4 [rcx+5*16]
+	aesdec4 [rcx+4*16]
+	aesdec4 [rcx+3*16]
+	aesdec4 [rcx+2*16]
+	aesdec4 [rcx+1*16]
+	aesdeclast4 [rcx+0*16]
+
+	pxor	xmm0,xmm5
+	movdqu	xmm4,[rdx - 16*4 + 0*16]
+	pxor	xmm1,xmm4
+	movdqu	xmm4,[rdx - 16*4 + 1*16]
+	pxor	xmm2,xmm4
+	movdqu	xmm4,[rdx - 16*4 + 2*16]
+	pxor	xmm3,xmm4
+	movdqu	xmm5,[rdx - 16*4 + 3*16]
+	
+	sub eax,4
+	store4 r8+rdx-(16*4)
+	jmp lp256decfour_CBC
+
+
+	align 16
+lp256decsingle_CBC:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4,[rcx+14*16]
+	movdqa	xmm1,xmm0
+	pxor xmm0, xmm4
+	aesdec1_u [rcx+13*16]
+	aesdec1_u [rcx+12*16]
+	aesdec1_u [rcx+11*16]
+	aesdec1_u [rcx+10*16]
+	aesdec1_u [rcx+9*16]
+	aesdec1_u [rcx+8*16]
+	aesdec1_u [rcx+7*16]
+	aesdec1_u [rcx+6*16]
+	aesdec1_u [rcx+5*16]
+	aesdec1_u [rcx+4*16]
+	aesdec1_u [rcx+3*16]
+	aesdec1_u [rcx+2*16]
+	aesdec1_u [rcx+1*16]
+	aesdeclast1_u [rcx+0*16]
+
+	pxor	xmm0,xmm5
+	movdqa	xmm5,xmm1
+	add rdx, 16
+	movdqu  [r8 + rdx - 16], xmm0
+	dec eax
+	jnz lp256decsingle_CBC
+
+end_dec256_CBC:
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm5
+	add rsp,16*16+8
+	ret
+
+
+
+
+
+align 16
+global iDec192
+iDec192:
+
+	linux_setup
+	sub rsp,16*16+8
+
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+	
+	test eax,eax
+	jz end_dec192
+
+	cmp eax,4
+	jl	lp192decsingle
+	
+	test	rcx,0xf
+	jz		lp192decfour
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	mov rcx,rsp	
+
+align 16
+lp192decfour:
+	
+	test eax,eax
+	jz end_dec192
+
+	cmp eax,4
+	jl	lp192decsingle
+
+	load_and_xor4 rdx, [rcx+12*16]
+	add rdx,16*4
+	aesdec4 [rcx+11*16]
+	aesdec4 [rcx+10*16]
+	aesdec4 [rcx+9*16]
+	aesdec4 [rcx+8*16]
+	aesdec4 [rcx+7*16]
+	aesdec4 [rcx+6*16]
+	aesdec4 [rcx+5*16]
+	aesdec4 [rcx+4*16]
+	aesdec4 [rcx+3*16]
+	aesdec4 [rcx+2*16]
+	aesdec4 [rcx+1*16]
+	aesdeclast4 [rcx+0*16]
+	
+	sub eax,4
+	store4 r8+rdx-(16*4)
+	jmp lp192decfour
+
+
+	align 16
+lp192decsingle:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4,[rcx+12*16]
+	pxor xmm0, xmm4
+	aesdec1_u [rcx+11*16]
+	aesdec1_u [rcx+10*16]
+	aesdec1_u [rcx+9*16]
+	aesdec1_u [rcx+8*16]
+	aesdec1_u [rcx+7*16]
+	aesdec1_u [rcx+6*16]
+	aesdec1_u [rcx+5*16]
+	aesdec1_u [rcx+4*16]
+	aesdec1_u [rcx+3*16]
+	aesdec1_u [rcx+2*16]
+	aesdec1_u [rcx+1*16]
+	aesdeclast1_u [rcx+0*16]
+
+	add rdx, 16
+	movdqu  [r8 + rdx - 16], xmm0
+	dec eax
+	jnz lp192decsingle
+
+end_dec192:
+
+	add rsp,16*16+8
+	ret
+
+
+
+
+align 16
+global iDec256
+iDec256:
+
+	linux_setup
+	sub rsp,16*16+8
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+
+	test eax,eax
+	jz end_dec256
+	
+	cmp eax,4
+	jl lp256dec
+
+	test	rcx,0xf
+	jz		lp256dec4
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	copy_round_keys rsp,rcx,13
+	copy_round_keys rsp,rcx,14
+	mov rcx,rsp	
+
+	
+	align 16
+lp256dec4:	
+	test eax,eax
+	jz end_dec256
+	
+	cmp eax,4
+	jl lp256dec
+	
+	load_and_xor4 rdx,[rcx+14*16]
+	add rdx, 4*16
+	aesdec4 [rcx+13*16]
+	aesdec4 [rcx+12*16]
+	aesdec4 [rcx+11*16]
+	aesdec4 [rcx+10*16]
+	aesdec4 [rcx+9*16]
+	aesdec4 [rcx+8*16]
+	aesdec4 [rcx+7*16]
+	aesdec4 [rcx+6*16]
+	aesdec4 [rcx+5*16]
+	aesdec4 [rcx+4*16]
+	aesdec4 [rcx+3*16]
+	aesdec4 [rcx+2*16]
+	aesdec4 [rcx+1*16]
+	aesdeclast4 [rcx+0*16]
+
+	store4 r8+rdx-16*4
+	sub eax,4
+	jmp lp256dec4	
+	
+	align 16
+lp256dec:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4,[rcx+14*16]
+	add rdx, 16
+	pxor xmm0, xmm4                    ; Round 0 (only xor)
+	aesdec1_u [rcx+13*16]
+	aesdec1_u [rcx+12*16]
+	aesdec1_u [rcx+11*16]
+	aesdec1_u [rcx+10*16]
+	aesdec1_u [rcx+9*16]
+	aesdec1_u [rcx+8*16]
+	aesdec1_u [rcx+7*16]
+	aesdec1_u [rcx+6*16]
+	aesdec1_u [rcx+5*16]
+	aesdec1_u [rcx+4*16]
+	aesdec1_u [rcx+3*16]
+	aesdec1_u [rcx+2*16]
+	aesdec1_u [rcx+1*16]
+	aesdeclast1_u [rcx+0*16]
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp256dec
+
+end_dec256:
+	
+	add rsp,16*16+8
+	ret
+
+
+
+
+
+
+align 16
+global iEnc128
+iEnc128:
+
+	linux_setup
+	sub rsp,16*16+8
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+
+	test eax,eax
+	jz end_enc128
+	
+	cmp eax,4
+	jl lp128encsingle
+
+	test	rcx,0xf
+	jz		lpenc128four
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	mov rcx,rsp	
+
+
+	align 16	
+	
+lpenc128four:
+	
+	test eax,eax
+	jz end_enc128
+	
+	cmp eax,4
+	jl lp128encsingle
+
+	load_and_xor4 rdx,[rcx+0*16]
+	add rdx,4*16
+	aesenc4	[rcx+1*16]
+	aesenc4	[rcx+2*16]
+	aesenc4	[rcx+3*16]
+	aesenc4	[rcx+4*16]
+	aesenc4	[rcx+5*16]
+	aesenc4	[rcx+6*16]
+	aesenc4	[rcx+7*16]
+	aesenc4	[rcx+8*16]
+	aesenc4	[rcx+9*16]
+	aesenclast4	[rcx+10*16]
+	
+	store4 r8+rdx-16*4
+	sub eax,4
+	jmp lpenc128four
+	
+	align 16
+lp128encsingle:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4,[rcx+0*16]
+	add rdx, 16
+	pxor xmm0, xmm4
+	aesenc1_u [rcx+1*16]
+	aesenc1_u [rcx+2*16]
+	aesenc1_u [rcx+3*16]
+	aesenc1_u [rcx+4*16]     
+	aesenc1_u [rcx+5*16]
+	aesenc1_u [rcx+6*16]
+	aesenc1_u [rcx+7*16]
+	aesenc1_u [rcx+8*16]
+	aesenc1_u [rcx+9*16]
+	aesenclast1_u [rcx+10*16]
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp128encsingle
+
+end_enc128:
+
+	add rsp,16*16+8
+	ret
+
+
+align 16
+global iEnc128_CTR
+iEnc128_CTR:
+
+	linux_setup
+
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu xmm5,[rax]
+
+
+	sub rsp,16*16+8
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+
+	test eax,eax
+	jz end_encctr128
+	
+	cmp eax,4
+	jl lp128encctrsingle
+
+	test	rcx,0xf
+	jz		lpencctr128four
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	mov rcx,rsp	
+
+
+	align 16	
+	
+lpencctr128four:
+	
+	test eax,eax
+	jz end_encctr128
+	
+	cmp eax,4
+	jl lp128encctrsingle
+
+	load_and_inc4 [rcx+0*16]
+	add rdx,4*16
+	aesenc4	[rcx+1*16]
+	aesenc4	[rcx+2*16]
+	aesenc4	[rcx+3*16]
+	aesenc4	[rcx+4*16]
+	aesenc4	[rcx+5*16]
+	aesenc4	[rcx+6*16]
+	aesenc4	[rcx+7*16]
+	aesenc4	[rcx+8*16]
+	aesenc4	[rcx+9*16]
+	aesenclast4	[rcx+10*16]
+	xor_with_input4 rdx-(4*16)
+	
+	store4 r8+rdx-16*4
+	sub eax,4
+	jmp lpencctr128four
+	
+	align 16
+lp128encctrsingle:
+
+	movdqa xmm0,xmm5
+	paddq	xmm5,[counter_add_one wrt rip]
+	add rdx, 16
+	movdqu xmm4,[rcx+0*16]
+	pxor xmm0, xmm4
+	aesenc1_u [rcx+1*16]
+	aesenc1_u [rcx+2*16]
+	aesenc1_u [rcx+3*16]
+	aesenc1_u [rcx+4*16]     
+	aesenc1_u [rcx+5*16]
+	aesenc1_u [rcx+6*16]
+	aesenc1_u [rcx+7*16]
+	aesenc1_u [rcx+8*16]
+	aesenc1_u [rcx+9*16]
+	aesenclast1_u [rcx+10*16]
+	movdqu xmm4, [rdx-16]
+	pxor  xmm0,xmm4
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp128encctrsingle
+
+end_encctr128:
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm5
+	add rsp,16*16+8
+	ret
+
+
+
+align 16
+global iEnc192_CTR
+iEnc192_CTR:
+
+	linux_setup
+
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu xmm5,[rax]
+
+
+	sub rsp,16*16+8
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+
+	test eax,eax
+	jz end_encctr192
+	
+	cmp eax,4
+	jl lp192encctrsingle
+
+	test	rcx,0xf
+	jz		lpencctr192four
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	mov rcx,rsp	
+
+
+	align 16	
+	
+lpencctr192four:
+	
+	test eax,eax
+	jz end_encctr192
+	
+	cmp eax,4
+	jl lp192encctrsingle
+
+	load_and_inc4 [rcx+0*16]
+	add rdx,4*16
+	aesenc4	[rcx+1*16]
+	aesenc4	[rcx+2*16]
+	aesenc4	[rcx+3*16]
+	aesenc4	[rcx+4*16]
+	aesenc4	[rcx+5*16]
+	aesenc4	[rcx+6*16]
+	aesenc4	[rcx+7*16]
+	aesenc4	[rcx+8*16]
+	aesenc4	[rcx+9*16]
+	aesenc4	[rcx+10*16]
+	aesenc4	[rcx+11*16]
+	aesenclast4	[rcx+12*16]
+	xor_with_input4 rdx-(4*16)
+	
+	store4 r8+rdx-16*4
+	sub eax,4
+	jmp lpencctr192four
+	
+	align 16
+lp192encctrsingle:
+
+	movdqa xmm5,xmm0
+	movdqu xmm4,[rcx+0*16]
+	paddq	xmm5,[counter_add_one wrt rip]
+	add rdx, 16
+	pxor xmm0, xmm4
+	aesenc1_u [rcx+1*16]
+	aesenc1_u [rcx+2*16]
+	aesenc1_u [rcx+3*16]
+	aesenc1_u [rcx+4*16]     
+	aesenc1_u [rcx+5*16]
+	aesenc1_u [rcx+6*16]
+	aesenc1_u [rcx+7*16]
+	aesenc1_u [rcx+8*16]
+	aesenc1_u [rcx+9*16]
+	aesenc1_u [rcx+10*16]
+	aesenc1_u [rcx+11*16]
+	aesenclast1_u [rcx+12*16]
+	movdqu xmm4, [rdx]
+	pxor  xmm0,xmm4
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp192encctrsingle
+
+end_encctr192:
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm5
+	add rsp,16*16+8
+	ret
+
+
+align 16
+global iEnc256_CTR
+iEnc256_CTR:
+
+	linux_setup
+
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu xmm5,[rax]
+
+
+	sub rsp,16*16+8
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+
+	test eax,eax
+	jz end_encctr256
+	
+	cmp eax,4
+	jl lp256encctrsingle
+
+	test	rcx,0xf
+	jz		lpencctr256four
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	copy_round_keys rsp,rcx,13
+	copy_round_keys rsp,rcx,14
+	mov rcx,rsp	
+
+
+	align 16	
+	
+lpencctr256four:
+	
+	test eax,eax
+	jz end_encctr256
+	
+	cmp eax,4
+	jl lp256encctrsingle
+
+	load_and_inc4 [rcx+0*16]
+	add rdx,4*16
+	aesenc4	[rcx+1*16]
+	aesenc4	[rcx+2*16]
+	aesenc4	[rcx+3*16]
+	aesenc4	[rcx+4*16]
+	aesenc4	[rcx+5*16]
+	aesenc4	[rcx+6*16]
+	aesenc4	[rcx+7*16]
+	aesenc4	[rcx+8*16]
+	aesenc4	[rcx+9*16]
+	aesenc4	[rcx+10*16]
+	aesenc4	[rcx+11*16]
+	aesenc4	[rcx+12*16]
+	aesenc4	[rcx+13*16]
+	aesenclast4	[rcx+14*16]
+	xor_with_input4 rdx-(4*16)
+	
+	store4 r8+rdx-16*4
+	sub eax,4
+	jmp lpencctr256four
+	
+	align 16
+lp256encctrsingle:
+
+	movdqa xmm5,xmm0
+	movdqu xmm4,[rcx+0*16]
+	paddq	xmm5,[counter_add_one wrt rip]
+	add rdx, 16
+	pxor xmm0, xmm4
+	aesenc1_u [rcx+1*16]
+	aesenc1_u [rcx+2*16]
+	aesenc1_u [rcx+3*16]
+	aesenc1_u [rcx+4*16]     
+	aesenc1_u [rcx+5*16]
+	aesenc1_u [rcx+6*16]
+	aesenc1_u [rcx+7*16]
+	aesenc1_u [rcx+8*16]
+	aesenc1_u [rcx+9*16]
+	aesenc1_u [rcx+10*16]
+	aesenc1_u [rcx+11*16]
+	aesenc1_u [rcx+12*16]
+	aesenc1_u [rcx+13*16]
+	aesenclast1_u [rcx+14*16]
+	movdqu xmm4, [rdx]
+	pxor  xmm0,xmm4
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp256encctrsingle
+
+end_encctr256:
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm5
+	add rsp,16*16+8
+	ret
+
+
+
+
+
+
+
+align 16
+global iEnc128_CBC
+iEnc128_CBC:
+
+	linux_setup
+	sub rsp,16*16+8
+	
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu xmm1,[rax]
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+
+	test	rcx,0xf
+	jz		lp128encsingle_CBC
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	mov rcx,rsp	
+
+
+	align 16	
+	
+lp128encsingle_CBC:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4,[rcx+0*16]
+	add rdx, 16
+	pxor xmm0, xmm1
+	pxor xmm0, xmm4
+	aesenc1 [rcx+1*16]
+	aesenc1 [rcx+2*16]
+	aesenc1 [rcx+3*16]
+	aesenc1 [rcx+4*16]     
+	aesenc1 [rcx+5*16]
+	aesenc1 [rcx+6*16]
+	aesenc1 [rcx+7*16]
+	aesenc1 [rcx+8*16]
+	aesenc1 [rcx+9*16]
+	aesenclast1 [rcx+10*16]
+	movdqa xmm1,xmm0
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp128encsingle_CBC
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm1
+	add rsp,16*16+8
+	ret
+
+
+align 16
+global iEnc192_CBC
+iEnc192_CBC:
+
+	linux_setup
+	sub rsp,16*16+8
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu xmm1,[rax]
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+	test	rcx,0xf
+	jz		lp192encsingle_CBC
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	mov rcx,rsp	
+
+
+
+	align 16	
+	
+lp192encsingle_CBC:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4, [rcx+0*16]
+	add rdx, 16
+	pxor xmm0, xmm1
+	pxor xmm0, xmm4
+	aesenc1 [rcx+1*16]
+	aesenc1 [rcx+2*16]
+	aesenc1 [rcx+3*16]
+	aesenc1 [rcx+4*16]     
+	aesenc1 [rcx+5*16]
+	aesenc1 [rcx+6*16]
+	aesenc1 [rcx+7*16]
+	aesenc1 [rcx+8*16]
+	aesenc1 [rcx+9*16]
+	aesenc1 [rcx+10*16]
+	aesenc1 [rcx+11*16]
+	aesenclast1 [rcx+12*16]
+	movdqa xmm1,xmm0
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp192encsingle_CBC
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm1
+
+	add rsp,16*16+8
+	ret
+
+
+align 16
+global iEnc256_CBC
+iEnc256_CBC:
+
+	linux_setup
+	sub rsp,16*16+8
+	
+	mov r9,rcx
+	mov rax,[rcx+24]
+	movdqu xmm1,[rax]
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+	test	rcx,0xf
+	jz		lp256encsingle_CBC
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	copy_round_keys rsp,rcx,13
+	copy_round_keys rsp,rcx,14
+	mov rcx,rsp	
+
+	align 16	
+	
+lp256encsingle_CBC:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4, [rcx+0*16]
+	add rdx, 16
+	pxor xmm0, xmm1
+	pxor xmm0, xmm4
+	aesenc1 [rcx+1*16]
+	aesenc1 [rcx+2*16]
+	aesenc1 [rcx+3*16]
+	aesenc1 [rcx+4*16]     
+	aesenc1 [rcx+5*16]
+	aesenc1 [rcx+6*16]
+	aesenc1 [rcx+7*16]
+	aesenc1 [rcx+8*16]
+	aesenc1 [rcx+9*16]
+	aesenc1 [rcx+10*16]
+	aesenc1 [rcx+11*16]
+	aesenc1 [rcx+12*16]
+	aesenc1 [rcx+13*16]
+	aesenclast1 [rcx+14*16]
+	movdqa xmm1,xmm0
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp256encsingle_CBC
+
+	mov	   r9,[r9+24]
+	movdqu [r9],xmm1
+	add rsp,16*16+8
+	ret
+
+
+
+
+align 16
+global iEnc192
+iEnc192:
+
+	linux_setup
+	sub rsp,16*16+8
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+	
+	sub r8,rdx
+
+	test eax,eax
+	jz end_enc192
+	
+	cmp eax,4
+	jl lp192encsingle
+
+	test	rcx,0xf
+	jz		lpenc192four
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	mov rcx,rsp	
+
+
+	align 16	
+	
+lpenc192four:
+	
+	test eax,eax
+	jz end_enc192
+	
+	cmp eax,4
+	jl lp192encsingle
+
+	load_and_xor4 rdx,[rcx+0*16]
+	add rdx,4*16
+	aesenc4	[rcx+1*16]
+	aesenc4	[rcx+2*16]
+	aesenc4	[rcx+3*16]
+	aesenc4	[rcx+4*16]
+	aesenc4	[rcx+5*16]
+	aesenc4	[rcx+6*16]
+	aesenc4	[rcx+7*16]
+	aesenc4	[rcx+8*16]
+	aesenc4	[rcx+9*16]
+	aesenc4	[rcx+10*16]
+	aesenc4	[rcx+11*16]
+	aesenclast4	[rcx+12*16]
+	
+	store4 r8+rdx-16*4
+	sub eax,4
+	jmp lpenc192four
+	
+	align 16
+lp192encsingle:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4, [rcx+0*16]
+	add rdx, 16
+	pxor xmm0, xmm4
+	aesenc1_u [rcx+1*16]
+	aesenc1_u [rcx+2*16]
+	aesenc1_u [rcx+3*16]
+	aesenc1_u [rcx+4*16]     
+	aesenc1_u [rcx+5*16]
+	aesenc1_u [rcx+6*16]
+	aesenc1_u [rcx+7*16]
+	aesenc1_u [rcx+8*16]
+	aesenc1_u [rcx+9*16]
+	aesenc1_u [rcx+10*16]
+	aesenc1_u [rcx+11*16]
+	aesenclast1_u [rcx+12*16]
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp192encsingle
+
+end_enc192:
+
+	add rsp,16*16+8
+	ret
+
+
+
+
+
+
+align 16
+global iEnc256
+iEnc256:
+
+	linux_setup
+	sub rsp,16*16+8
+	
+	mov eax,[rcx+32] ; numblocks
+	mov rdx,[rcx]
+	mov r8,[rcx+8]
+	mov rcx,[rcx+16]
+
+	sub r8,rdx	
+
+
+	test eax,eax
+	jz end_enc256
+
+	cmp eax,4
+	jl lp256enc
+
+	test	rcx,0xf
+	jz		lp256enc4
+	
+	copy_round_keys rsp,rcx,0
+	copy_round_keys rsp,rcx,1
+	copy_round_keys rsp,rcx,2
+	copy_round_keys rsp,rcx,3
+	copy_round_keys rsp,rcx,4
+	copy_round_keys rsp,rcx,5
+	copy_round_keys rsp,rcx,6
+	copy_round_keys rsp,rcx,7
+	copy_round_keys rsp,rcx,8
+	copy_round_keys rsp,rcx,9
+	copy_round_keys rsp,rcx,10
+	copy_round_keys rsp,rcx,11
+	copy_round_keys rsp,rcx,12
+	copy_round_keys rsp,rcx,13
+	copy_round_keys rsp,rcx,14
+	mov rcx,rsp	
+
+
+	align 16
+	
+lp256enc4:
+	test eax,eax
+	jz end_enc256
+
+	cmp eax,4
+	jl lp256enc
+
+
+	load_and_xor4 rdx,[rcx+0*16]
+	add rdx, 16*4
+	aesenc4 [rcx+1*16]
+	aesenc4 [rcx+2*16]
+	aesenc4 [rcx+3*16]
+	aesenc4 [rcx+4*16]
+	aesenc4 [rcx+5*16]
+	aesenc4 [rcx+6*16]
+	aesenc4 [rcx+7*16]
+	aesenc4 [rcx+8*16]
+	aesenc4 [rcx+9*16]
+	aesenc4 [rcx+10*16]
+	aesenc4 [rcx+11*16]
+	aesenc4 [rcx+12*16]
+	aesenc4 [rcx+13*16]
+	aesenclast4 [rcx+14*16]
+
+	store4  r8+rdx-16*4
+	sub eax,4
+	jmp lp256enc4
+	
+	align 16
+lp256enc:
+
+	movdqu xmm0, [rdx]
+	movdqu xmm4, [rcx+0*16]
+	add rdx, 16
+	pxor xmm0, xmm4
+	aesenc1_u [rcx+1*16]
+	aesenc1_u [rcx+2*16]
+	aesenc1_u [rcx+3*16]
+	aesenc1_u [rcx+4*16]
+	aesenc1_u [rcx+5*16]
+	aesenc1_u [rcx+6*16]
+	aesenc1_u [rcx+7*16]
+	aesenc1_u [rcx+8*16]
+	aesenc1_u [rcx+9*16]
+	aesenc1_u [rcx+10*16]
+	aesenc1_u [rcx+11*16]
+	aesenc1_u [rcx+12*16]
+	aesenc1_u [rcx+13*16]
+	aesenclast1_u [rcx+14*16]
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [r8+rdx-16], xmm0
+	dec eax
+	jnz lp256enc
+
+end_enc256:
+
+	add rsp,16*16+8
+	ret
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x86/do_rdtsc.s view
@@ -0,0 +1,35 @@+[bits 32]
+[CPU intelnop]
+
+; Copyright (c) 2010, Intel Corporation
+; All rights reserved.
+; 
+; Redistribution and use in source and binary forms, with or without 
+; modification, are permitted provided that the following conditions are met:
+; 
+;     * Redistributions of source code must retain the above copyright notice, 
+;       this list of conditions and the following disclaimer.
+;     * 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.
+;     * Neither the name of Intel Corporation nor the names of its contributors 
+;       may be used to endorse or promote products derived from this software 
+;       without specific prior written permission.
+; 
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+align 16
+global _do_rdtsc
+_do_rdtsc:
+
+	rdtsc
+	ret
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x86/iaesx86.s view
@@ -0,0 +1,2183 @@+[bits 32]
+[CPU intelnop]
+
+; Copyright (c) 2010, Intel Corporation
+; All rights reserved.
+; 
+; Redistribution and use in source and binary forms, with or without 
+; modification, are permitted provided that the following conditions are met:
+; 
+;     * Redistributions of source code must retain the above copyright notice, 
+;       this list of conditions and the following disclaimer.
+;     * 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.
+;     * Neither the name of Intel Corporation nor the names of its contributors 
+;       may be used to endorse or promote products derived from this software 
+;       without specific prior written permission.
+; 
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+
+%macro inversekey 1
+	movdqu  xmm1,%1
+	aesimc	xmm0,xmm1
+	movdqu	%1,xmm0
+%endmacro
+
+
+%macro aesdec4 1
+	movdqa	xmm4,%1
+
+	aesdec	xmm0,xmm4
+	aesdec	xmm1,xmm4
+	aesdec	xmm2,xmm4
+	aesdec	xmm3,xmm4
+
+%endmacro
+
+
+%macro aesdeclast4 1
+	movdqa	xmm4,%1
+
+	aesdeclast	xmm0,xmm4
+	aesdeclast	xmm1,xmm4
+	aesdeclast	xmm2,xmm4
+	aesdeclast	xmm3,xmm4
+
+%endmacro
+
+
+%macro aesenc4 1
+	movdqa	xmm4,%1
+
+	aesenc	xmm0,xmm4
+	aesenc	xmm1,xmm4
+	aesenc	xmm2,xmm4
+	aesenc	xmm3,xmm4
+
+%endmacro
+
+%macro aesenclast4 1
+	movdqa	xmm4,%1
+
+	aesenclast	xmm0,xmm4
+	aesenclast	xmm1,xmm4
+	aesenclast	xmm2,xmm4
+	aesenclast	xmm3,xmm4
+
+%endmacro
+
+
+%macro aesdeclast1 1
+	aesdeclast	xmm0,%1
+%endmacro
+
+%macro aesenclast1 1
+	aesenclast	xmm0,%1
+%endmacro
+
+%macro aesdec1 1
+	aesdec	xmm0,%1
+%endmacro
+
+;abab
+%macro aesenc1 1
+	aesenc	xmm0,%1
+%endmacro
+
+
+%macro aesdeclast1_u 1
+	movdqu xmm4,%1
+	aesdeclast	xmm0,xmm4
+%endmacro
+
+%macro aesenclast1_u 1
+	movdqu xmm4,%1
+	aesenclast	xmm0,xmm4
+%endmacro
+
+%macro aesdec1_u 1
+	movdqu xmm4,%1
+	aesdec	xmm0,xmm4
+%endmacro
+
+%macro aesenc1_u 1
+	movdqu xmm4,%1
+	aesenc	xmm0,xmm4
+%endmacro
+
+
+%macro load_and_xor4 2
+	movdqa	xmm4,%2
+	movdqu	xmm0,[%1 + 0*16]
+	pxor	xmm0,xmm4
+	movdqu	xmm1,[%1 + 1*16]
+	pxor	xmm1,xmm4
+	movdqu	xmm2,[%1 + 2*16]
+	pxor	xmm2,xmm4
+	movdqu	xmm3,[%1 + 3*16]
+	pxor	xmm3,xmm4
+%endmacro
+
+
+%macro load_and_inc4 1
+	movdqa	xmm4,%1
+	movdqa	xmm0,xmm5
+	movdqa  xmm1,xmm5
+	paddq	xmm1,[counter_add_one]
+	movdqa  xmm2,xmm5
+	paddq	xmm2,[counter_add_two]
+	movdqa  xmm3,xmm5
+	paddq	xmm3,[counter_add_three]
+	pxor	xmm0,xmm4
+	paddq	xmm5,[counter_add_four]
+	pxor	xmm1,xmm4
+	pxor	xmm2,xmm4
+	pxor	xmm3,xmm4
+%endmacro
+
+%macro xor_with_input4 1
+	movdqu xmm4,[%1]
+	pxor xmm0,xmm4
+	movdqu xmm4,[%1+16]
+	pxor xmm1,xmm4
+	movdqu xmm4,[%1+32]
+	pxor xmm2,xmm4
+	movdqu xmm4,[%1+48]
+	pxor xmm3,xmm4
+%endmacro
+
+%macro store4 1
+	movdqu [%1 + 0*16],xmm0
+	movdqu [%1 + 1*16],xmm1
+	movdqu [%1 + 2*16],xmm2
+	movdqu [%1 + 3*16],xmm3
+%endmacro
+
+
+%macro copy_round_keys 3
+	movdqu xmm4,[%2 + ((%3)*16)]
+	movdqa [%1 + ((%3)*16)],xmm4
+%endmacro
+
+;abab
+%macro copy_round_keyx 3
+	movdqu xmm4,[%2 + ((%3)*16)]
+	movdqa %1,xmm4
+%endmacro
+
+
+
+%macro key_expansion_1_192 1
+		;; Assumes the xmm3 includes all zeros at this point. 
+        pshufd xmm2, xmm2, 11111111b        
+        shufps xmm3, xmm1, 00010000b        
+        pxor xmm1, xmm3        
+        shufps xmm3, xmm1, 10001100b
+        pxor xmm1, xmm3        
+		pxor xmm1, xmm2		
+		movdqu [edx+%1], xmm1			
+%endmacro
+
+; Calculate w10 and w11 using calculated w9 and known w4-w5
+%macro key_expansion_2_192 1				
+		movdqa xmm5, xmm4
+		pslldq xmm5, 4
+		shufps xmm6, xmm1, 11110000b
+		pxor xmm6, xmm5
+		pxor xmm4, xmm6
+		pshufd xmm7, xmm4, 00001110b 
+		movdqu [edx+%1], xmm7
+%endmacro
+
+
+
+
+
+section .data
+align 16
+shuffle_mask:
+DD 0FFFFFFFFh
+DD 03020100h
+DD 07060504h
+DD 0B0A0908h
+
+align 16
+counter_add_one:
+DD 1
+DD 0
+DD 0
+DD 0
+
+counter_add_two:
+DD 2
+DD 0
+DD 0
+DD 0
+
+counter_add_three:
+DD 3
+DD 0
+DD 0
+DD 0
+
+counter_add_four:
+DD 4
+DD 0
+DD 0
+DD 0
+
+
+section .text
+
+
+
+align 16
+key_expansion256:
+
+    pshufd xmm2, xmm2, 011111111b
+
+    movdqu xmm4, xmm1
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pxor xmm1, xmm2
+
+    movdqu [edx], xmm1
+    add edx, 0x10
+    
+    aeskeygenassist xmm4, xmm1, 0
+    pshufd xmm2, xmm4, 010101010b
+
+    movdqu xmm4, xmm3
+    pshufb xmm4, xmm5
+    pxor xmm3, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm3, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm3, xmm4
+    pxor xmm3, xmm2
+
+    movdqu [edx], xmm3
+    add edx, 0x10
+
+    ret
+
+
+
+align 16
+key_expansion128: 
+    pshufd xmm2, xmm2, 0xFF;
+    movdqu xmm3, xmm1
+    pshufb xmm3, xmm5
+    pxor xmm1, xmm3
+    pshufb xmm3, xmm5
+    pxor xmm1, xmm3
+    pshufb xmm3, xmm5
+    pxor xmm1, xmm3
+    pxor xmm1, xmm2
+
+    ; storing the result in the key schedule array
+    movdqu [edx], xmm1
+    add edx, 0x10                    
+    ret
+
+
+
+align 16
+global _iEncExpandKey128
+_iEncExpandKey128:
+
+	mov ecx,[esp-4+8]		;input
+	mov edx,[esp-4+12]		;ctx
+
+        movdqu xmm1, [ecx]    ; loading the key
+
+        movdqu [edx], xmm1
+
+        movdqa xmm5, [shuffle_mask]
+
+        add edx,16
+
+        aeskeygenassist xmm2, xmm1, 0x1     ; Generating round key 1
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x2     ; Generating round key 2
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x4     ; Generating round key 3
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x8     ; Generating round key 4
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x10    ; Generating round key 5
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x20    ; Generating round key 6
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x40    ; Generating round key 7
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x80    ; Generating round key 8
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x1b    ; Generating round key 9
+        call key_expansion128
+        aeskeygenassist xmm2, xmm1, 0x36    ; Generating round key 10
+        call key_expansion128
+
+	ret
+
+
+align 16
+global _iEncExpandKey192
+_iEncExpandKey192:
+
+	mov ecx,[esp-4+8]		;input
+	mov edx,[esp-4+12]		;ctx
+
+        movq xmm7, [ecx+16]	; loading the AES key
+        movq [edx+16], xmm7  ; Storing key in memory where all key expansion 
+        pshufd xmm4, xmm7, 01001111b
+        movdqu xmm1, [ecx]	; loading the AES key
+        movdqu [edx], xmm1  ; Storing key in memory where all key expansion 
+			
+        pxor xmm3, xmm3		; Set xmm3 to be all zeros. Required for the key_expansion. 
+        pxor xmm6, xmm6		; Set xmm3 to be all zeros. Required for the key_expansion. 
+
+        aeskeygenassist xmm2, xmm4, 0x1     ; Complete round key 1 and generate round key 2 
+        key_expansion_1_192 24
+	key_expansion_2_192 40				
+
+        aeskeygenassist xmm2, xmm4, 0x2     ; Generate round key 3 and part of round key 4
+        key_expansion_1_192 48
+	key_expansion_2_192 64				
+
+        aeskeygenassist xmm2, xmm4, 0x4     ; Complete round key 4 and generate round key 5
+        key_expansion_1_192 72
+	key_expansion_2_192 88
+		
+        aeskeygenassist xmm2, xmm4, 0x8     ; Generate round key 6 and part of round key 7
+        key_expansion_1_192 96
+	key_expansion_2_192 112
+		
+        aeskeygenassist xmm2, xmm4, 0x10     ; Complete round key 7 and generate round key 8 
+        key_expansion_1_192 120
+	key_expansion_2_192 136				
+
+        aeskeygenassist xmm2, xmm4, 0x20     ; Generate round key 9 and part of round key 10
+        key_expansion_1_192 144
+	key_expansion_2_192 160				
+
+        aeskeygenassist xmm2, xmm4, 0x40     ; Complete round key 10 and generate round key 11
+        key_expansion_1_192 168
+	key_expansion_2_192 184				
+
+        aeskeygenassist xmm2, xmm4, 0x80     ; Generate round key 12
+        key_expansion_1_192 192
+
+	ret
+
+
+
+
+
+
+align 16
+global _iDecExpandKey128
+_iDecExpandKey128:
+	push DWORD [esp+8]
+	push DWORD [esp+8]
+	
+	call _iEncExpandKey128
+	add esp,8
+
+	mov edx,[esp-4+12]		;ctx
+	
+	inversekey	[edx + 1*16]
+	inversekey	[edx + 2*16]
+	inversekey	[edx + 3*16]
+	inversekey	[edx + 4*16]
+	inversekey	[edx + 5*16]
+	inversekey	[edx + 6*16]
+	inversekey	[edx + 7*16]
+	inversekey	[edx + 8*16]
+	inversekey	[edx + 9*16]
+
+	ret
+
+
+
+
+align 16
+global _iDecExpandKey192
+_iDecExpandKey192:
+	push DWORD [esp+8]
+	push DWORD [esp+8]
+	
+	call _iEncExpandKey192
+	add esp,8
+
+	mov edx,[esp-4+12]		;ctx
+	
+	inversekey	[edx + 1*16]
+	inversekey	[edx + 2*16]
+	inversekey	[edx + 3*16]
+	inversekey	[edx + 4*16]
+	inversekey	[edx + 5*16]
+	inversekey	[edx + 6*16]
+	inversekey	[edx + 7*16]
+	inversekey	[edx + 8*16]
+	inversekey	[edx + 9*16]
+	inversekey	[edx + 10*16]
+	inversekey	[edx + 11*16]
+
+	ret
+
+
+
+
+align 16
+global _iDecExpandKey256
+_iDecExpandKey256:
+	push DWORD [esp+8]
+	push DWORD [esp+8]
+	
+	call _iEncExpandKey256
+	add esp, 8
+
+	mov edx, [esp-4+12]		;expanded key
+	
+	inversekey	[edx + 1*16]
+	inversekey	[edx + 2*16]
+	inversekey	[edx + 3*16]
+	inversekey	[edx + 4*16]
+	inversekey	[edx + 5*16]
+	inversekey	[edx + 6*16]
+	inversekey	[edx + 7*16]
+	inversekey	[edx + 8*16]
+	inversekey	[edx + 9*16]
+	inversekey	[edx + 10*16]
+	inversekey	[edx + 11*16]
+	inversekey	[edx + 12*16]
+	inversekey	[edx + 13*16]
+
+	ret
+	
+
+	
+	
+align 16
+global _iEncExpandKey256
+_iEncExpandKey256:
+	mov ecx, [esp-4+8]		;input
+	mov edx, [esp-4+12]		;expanded key
+
+
+    movdqu xmm1, [ecx]    ; loading the key
+    movdqu xmm3, [ecx+16]
+    movdqu [edx], xmm1  ; Storing key in memory where all key schedule will be stored
+    movdqu [edx+16], xmm3 
+    
+    add edx,32
+
+    movdqa xmm5, [shuffle_mask]  ; this mask is used by key_expansion
+
+    aeskeygenassist xmm2, xmm3, 0x1     ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x2     ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x4     ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x8     ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x10    ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x20    ; 
+    call key_expansion256
+    aeskeygenassist xmm2, xmm3, 0x40    ; 
+;    call key_expansion256 
+
+    pshufd xmm2, xmm2, 011111111b
+
+    movdqu xmm4, xmm1
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pshufb xmm4, xmm5
+    pxor xmm1, xmm4
+    pxor xmm1, xmm2
+
+    movdqu [edx], xmm1
+
+
+	ret
+	
+	
+	
+	
+	
+
+align 16
+global _iDec128
+_iDec128:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+	
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+
+	sub edi,esi
+	
+	test eax,eax
+	jz end_dec128
+
+	cmp eax,4
+	jl	lp128decsingle
+
+	test	ecx,0xf
+	jz		lp128decfour
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	mov ecx,esp	
+	
+
+align 16
+lp128decfour:
+	
+	test eax,eax
+	jz end_dec128
+
+	cmp eax,4
+	jl	lp128decsingle
+
+	load_and_xor4 esi, [ecx+10*16]
+	add esi,16*4
+	aesdec4 [ecx+9*16]
+	aesdec4 [ecx+8*16]
+	aesdec4 [ecx+7*16]
+	aesdec4 [ecx+6*16]
+	aesdec4 [ecx+5*16]
+	aesdec4 [ecx+4*16]
+	aesdec4 [ecx+3*16]
+	aesdec4 [ecx+2*16]
+	aesdec4 [ecx+1*16]
+	aesdeclast4 [ecx+0*16]
+	
+	sub eax,4
+	store4 esi+edi-(16*4)
+	jmp lp128decfour
+
+
+	align 16
+lp128decsingle:
+
+	movdqu xmm0, [esi]
+	movdqu xmm4,[ecx+10*16]
+	pxor xmm0, xmm4
+	aesdec1_u  [ecx+9*16]
+	aesdec1_u  [ecx+8*16]
+	aesdec1_u  [ecx+7*16]
+	aesdec1_u  [ecx+6*16]
+	aesdec1_u  [ecx+5*16]
+	aesdec1_u  [ecx+4*16]
+	aesdec1_u  [ecx+3*16]
+	aesdec1_u  [ecx+2*16]
+	aesdec1_u  [ecx+1*16]
+	aesdeclast1_u [ecx+0*16]
+
+	add esi, 16
+	movdqu  [edi+esi - 16], xmm0
+	dec eax
+	jnz lp128decsingle
+
+end_dec128:
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	
+	ret
+
+
+
+align 16
+global _iDec128_CBC
+_iDec128_CBC:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	sub esp,16*16
+	and esp,0xfffffff0
+	
+	mov eax,[ecx+12]
+	movdqu xmm5,[eax]	;iv
+	
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_dec128_CBC
+
+	cmp eax,4
+	jl	lp128decsingle_CBC
+
+	test	ecx,0xf
+	jz		lp128decfour_CBC
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	mov ecx,esp	
+
+
+align 16
+lp128decfour_CBC:
+	
+	test eax,eax
+	jz end_dec128_CBC
+
+	cmp eax,4
+	jl	lp128decsingle_CBC
+
+	load_and_xor4 esi, [ecx+10*16]
+	add esi,16*4
+	aesdec4 [ecx+9*16]
+	aesdec4 [ecx+8*16]
+	aesdec4 [ecx+7*16]
+	aesdec4 [ecx+6*16]
+	aesdec4 [ecx+5*16]
+	aesdec4 [ecx+4*16]
+	aesdec4 [ecx+3*16]
+	aesdec4 [ecx+2*16]
+	aesdec4 [ecx+1*16]
+	aesdeclast4 [ecx+0*16]
+	
+	pxor	xmm0,xmm5
+	movdqu	xmm4,[esi- 16*4 + 0*16]
+	pxor	xmm1,xmm4
+	movdqu	xmm4,[esi- 16*4 + 1*16]
+	pxor	xmm2,xmm4
+	movdqu	xmm4,[esi- 16*4 + 2*16]
+	pxor	xmm3,xmm4
+	movdqu	xmm5,[esi- 16*4 + 3*16]
+	
+	sub eax,4
+	store4 esi+edi-(16*4)
+	jmp lp128decfour_CBC
+
+
+	align 16
+lp128decsingle_CBC:
+
+	movdqu xmm0, [esi]
+	movdqa xmm1,xmm0
+	movdqu xmm4,[ecx+10*16]
+	pxor xmm0, xmm4
+	aesdec1_u  [ecx+9*16]
+	aesdec1_u  [ecx+8*16]
+	aesdec1_u  [ecx+7*16]
+	aesdec1_u  [ecx+6*16]
+	aesdec1_u  [ecx+5*16]
+	aesdec1_u  [ecx+4*16]
+	aesdec1_u  [ecx+3*16]
+	aesdec1_u  [ecx+2*16]
+	aesdec1_u  [ecx+1*16]
+	aesdeclast1_u [ecx+0*16]
+	
+	pxor	xmm0,xmm5
+	movdqa	xmm5,xmm1
+	
+	add esi, 16
+	movdqu  [edi+esi - 16], xmm0
+	dec eax
+	jnz lp128decsingle_CBC
+
+end_dec128_CBC:
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+
+	mov ecx,[esp-4+8]   ; first arg
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm5 ; store last iv for chaining
+	
+	ret
+
+
+
+
+
+
+align 16
+global _iDec192
+_iDec192:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+	
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_dec192
+
+	cmp eax,4
+	jl	lp192decsingle
+
+	test	ecx,0xf
+	jz		lp192decfour
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	mov ecx,esp	
+
+
+align 16
+lp192decfour:
+	
+	test eax,eax
+	jz end_dec192
+
+	cmp eax,4
+	jl	lp192decsingle
+
+	load_and_xor4 esi, [ecx+12*16]
+	add esi,16*4
+	aesdec4 [ecx+11*16]
+	aesdec4 [ecx+10*16]
+	aesdec4 [ecx+9*16]
+	aesdec4 [ecx+8*16]
+	aesdec4 [ecx+7*16]
+	aesdec4 [ecx+6*16]
+	aesdec4 [ecx+5*16]
+	aesdec4 [ecx+4*16]
+	aesdec4 [ecx+3*16]
+	aesdec4 [ecx+2*16]
+	aesdec4 [ecx+1*16]
+	aesdeclast4 [ecx+0*16]
+	
+	sub eax,4
+	store4 esi+edi-(16*4)
+	jmp lp192decfour
+
+
+	align 16
+lp192decsingle:
+
+	movdqu xmm0, [esi]
+	movdqu xmm4,[ecx+12*16]
+	pxor xmm0, xmm4
+	aesdec1_u [ecx+11*16]
+	aesdec1_u  [ecx+10*16]
+	aesdec1_u  [ecx+9*16]
+	aesdec1_u  [ecx+8*16]
+	aesdec1_u  [ecx+7*16]
+	aesdec1_u  [ecx+6*16]
+	aesdec1_u  [ecx+5*16]
+	aesdec1_u  [ecx+4*16]
+	aesdec1_u  [ecx+3*16]
+	aesdec1_u  [ecx+2*16]
+	aesdec1_u  [ecx+1*16]
+	aesdeclast1_u  [ecx+0*16]
+
+	add esi, 16
+	movdqu  [edi+esi - 16], xmm0
+	dec eax
+	jnz lp192decsingle
+
+end_dec192:
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	
+	ret
+
+
+align 16
+global _iDec192_CBC
+_iDec192_CBC:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov eax,[ecx+12]
+	movdqu xmm5,[eax]	;iv
+	
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_dec192_CBC
+
+	cmp eax,4
+	jl	lp192decsingle_CBC
+
+	test	ecx,0xf
+	jz		lp192decfour_CBC
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	mov ecx,esp	
+
+align 16
+lp192decfour_CBC:
+	
+	test eax,eax
+	jz end_dec192_CBC
+
+	cmp eax,4
+	jl	lp192decsingle_CBC
+
+	load_and_xor4 esi, [ecx+12*16]
+	add esi,16*4
+	aesdec4 [ecx+11*16]
+	aesdec4 [ecx+10*16]
+	aesdec4 [ecx+9*16]
+	aesdec4 [ecx+8*16]
+	aesdec4 [ecx+7*16]
+	aesdec4 [ecx+6*16]
+	aesdec4 [ecx+5*16]
+	aesdec4 [ecx+4*16]
+	aesdec4 [ecx+3*16]
+	aesdec4 [ecx+2*16]
+	aesdec4 [ecx+1*16]
+	aesdeclast4 [ecx+0*16]
+	
+	pxor	xmm0,xmm5
+	movdqu	xmm4,[esi- 16*4 + 0*16]
+	pxor	xmm1,xmm4
+	movdqu	xmm4,[esi- 16*4 + 1*16]
+	pxor	xmm2,xmm4
+	movdqu	xmm4,[esi- 16*4 + 2*16]
+	pxor	xmm3,xmm4
+	movdqu	xmm5,[esi- 16*4 + 3*16]
+	
+	sub eax,4
+	store4 esi+edi-(16*4)
+	jmp lp192decfour_CBC
+
+
+	align 16
+lp192decsingle_CBC:
+
+	movdqu xmm0, [esi]
+	movdqu xmm4,[ecx+12*16]
+	movdqa xmm1,xmm0
+	pxor xmm0, xmm4
+	aesdec1_u [ecx+11*16]
+	aesdec1_u [ecx+10*16]
+	aesdec1_u [ecx+9*16]
+	aesdec1_u [ecx+8*16]
+	aesdec1_u [ecx+7*16]
+	aesdec1_u [ecx+6*16]
+	aesdec1_u [ecx+5*16]
+	aesdec1_u [ecx+4*16]
+	aesdec1_u [ecx+3*16]
+	aesdec1_u [ecx+2*16]
+	aesdec1_u [ecx+1*16]
+	aesdeclast1_u [ecx+0*16]
+	
+	pxor	xmm0,xmm5
+	movdqa	xmm5,xmm1
+	
+	add esi, 16
+	movdqu  [edi+esi - 16], xmm0
+	dec eax
+	jnz lp192decsingle_CBC
+
+end_dec192_CBC:
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+
+	mov ecx,[esp-4+8]
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm5 ; store last iv for chaining
+	
+	ret
+
+
+
+
+
+align 16
+global _iDec256
+_iDec256:
+	mov ecx, [esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+
+	test eax,eax
+	jz end_dec256
+	
+	cmp eax,4
+	jl lp256dec
+
+	test	ecx,0xf
+	jz	lp256dec4
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	copy_round_keys esp,ecx,13
+	copy_round_keys esp,ecx,14
+	mov ecx,esp	
+	
+	align 16
+lp256dec4:
+	test eax,eax
+	jz end_dec256
+	
+	cmp eax,4
+	jl lp256dec
+	
+	load_and_xor4 esi,[ecx+14*16]
+	add esi, 4*16
+	aesdec4 [ecx+13*16]
+	aesdec4 [ecx+12*16]
+	aesdec4 [ecx+11*16]
+	aesdec4 [ecx+10*16]
+	aesdec4 [ecx+9*16]
+	aesdec4 [ecx+8*16]
+	aesdec4 [ecx+7*16]
+	aesdec4 [ecx+6*16]
+	aesdec4 [ecx+5*16]
+	aesdec4 [ecx+4*16]
+	aesdec4 [ecx+3*16]
+	aesdec4 [ecx+2*16]
+	aesdec4 [ecx+1*16]
+	aesdeclast4 [ecx+0*16]
+
+	store4 esi+edi-16*4
+	sub eax,4
+	jmp lp256dec4	
+	
+	align 16
+lp256dec:
+
+	movdqu xmm0, [esi]
+	movdqu xmm4,[ecx+14*16]
+	add esi, 16
+	pxor xmm0, xmm4                     ; Round 0 (only xor)
+	aesdec1_u  [ecx+13*16]
+	aesdec1_u  [ecx+12*16]
+	aesdec1_u  [ecx+11*16]
+	aesdec1_u  [ecx+10*16]
+	aesdec1_u  [ecx+9*16]
+	aesdec1_u  [ecx+8*16]
+	aesdec1_u  [ecx+7*16]
+	aesdec1_u  [ecx+6*16]
+	aesdec1_u  [ecx+5*16]
+	aesdec1_u  [ecx+4*16]
+	aesdec1_u  [ecx+3*16]
+	aesdec1_u  [ecx+2*16]
+	aesdec1_u  [ecx+1*16]
+	aesdeclast1_u  [ecx+0*16]
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	dec eax
+	jnz lp256dec
+
+end_dec256:
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	
+	ret
+
+
+
+
+align 16
+global _iDec256_CBC
+_iDec256_CBC:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov eax,[ecx+12]
+	movdqu xmm5,[eax]	;iv
+	
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_dec256_CBC
+
+	cmp eax,4
+	jl	lp256decsingle_CBC
+
+	test	ecx,0xf
+	jz	lp256decfour_CBC
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	copy_round_keys esp,ecx,13
+	copy_round_keys esp,ecx,14
+	mov ecx,esp	
+
+align 16
+lp256decfour_CBC:
+	
+	test eax,eax
+	jz end_dec256_CBC
+
+	cmp eax,4
+	jl	lp256decsingle_CBC
+
+	load_and_xor4 esi, [ecx+14*16]
+	add esi,16*4
+	aesdec4 [ecx+13*16]
+	aesdec4 [ecx+12*16]
+	aesdec4 [ecx+11*16]
+	aesdec4 [ecx+10*16]
+	aesdec4 [ecx+9*16]
+	aesdec4 [ecx+8*16]
+	aesdec4 [ecx+7*16]
+	aesdec4 [ecx+6*16]
+	aesdec4 [ecx+5*16]
+	aesdec4 [ecx+4*16]
+	aesdec4 [ecx+3*16]
+	aesdec4 [ecx+2*16]
+	aesdec4 [ecx+1*16]
+	aesdeclast4 [ecx+0*16]
+	
+	pxor	xmm0,xmm5
+	movdqu	xmm4,[esi- 16*4 + 0*16]
+	pxor	xmm1,xmm4
+	movdqu	xmm4,[esi- 16*4 + 1*16]
+	pxor	xmm2,xmm4
+	movdqu	xmm4,[esi- 16*4 + 2*16]
+	pxor	xmm3,xmm4
+	movdqu	xmm5,[esi- 16*4 + 3*16]
+	
+	sub eax,4
+	store4 esi+edi-(16*4)
+	jmp lp256decfour_CBC
+
+
+	align 16
+lp256decsingle_CBC:
+
+	movdqu xmm0, [esi]
+	movdqa xmm1,xmm0
+	movdqu xmm4, [ecx+14*16]
+	pxor xmm0, xmm4
+	aesdec1_u  [ecx+13*16]
+	aesdec1_u  [ecx+12*16]
+	aesdec1_u  [ecx+11*16]
+	aesdec1_u  [ecx+10*16]
+	aesdec1_u  [ecx+9*16]
+	aesdec1_u  [ecx+8*16]
+	aesdec1_u  [ecx+7*16]
+	aesdec1_u  [ecx+6*16]
+	aesdec1_u  [ecx+5*16]
+	aesdec1_u  [ecx+4*16]
+	aesdec1_u  [ecx+3*16]
+	aesdec1_u  [ecx+2*16]
+	aesdec1_u  [ecx+1*16]
+	aesdeclast1_u  [ecx+0*16]
+	
+	pxor	xmm0,xmm5
+	movdqa	xmm5,xmm1
+	
+	add esi, 16
+	movdqu  [edi+esi - 16], xmm0
+	dec eax
+	jnz lp256decsingle_CBC
+
+end_dec256_CBC:
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+
+	mov ecx,[esp-4+8]  ; first arg
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm5 ; store last iv for chaining
+	
+	ret
+
+
+
+
+
+
+
+
+
+align 16
+global _iEnc128
+_iEnc128:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_enc128
+	
+	cmp eax,4
+	jl lp128encsingle
+
+	test	ecx,0xf
+	jz		lpenc128four
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	mov ecx,esp	
+
+
+	align 16	
+	
+lpenc128four:
+	
+	test eax,eax
+	jz end_enc128
+	
+	cmp eax,4
+	jl lp128encsingle
+
+	load_and_xor4 esi,[ecx+0*16]
+	add esi,4*16
+	aesenc4	[ecx+1*16]
+	aesenc4	[ecx+2*16]
+	aesenc4	[ecx+3*16]
+	aesenc4	[ecx+4*16]
+	aesenc4	[ecx+5*16]
+	aesenc4	[ecx+6*16]
+	aesenc4	[ecx+7*16]
+	aesenc4	[ecx+8*16]
+	aesenc4	[ecx+9*16]
+	aesenclast4	[ecx+10*16]
+	
+	store4 esi+edi-16*4
+	sub eax,4
+	jmp lpenc128four
+	
+	align 16
+lp128encsingle:
+
+	movdqu xmm0, [esi]
+	add esi, 16
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1_u  [ecx+1*16]
+	aesenc1_u  [ecx+2*16]
+	aesenc1_u  [ecx+3*16]
+	aesenc1_u  [ecx+4*16]     
+	aesenc1_u  [ecx+5*16]
+	aesenc1_u  [ecx+6*16]
+	aesenc1_u  [ecx+7*16]
+	aesenc1_u  [ecx+8*16]
+	aesenc1_u  [ecx+9*16]
+	aesenclast1_u  [ecx+10*16]
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	dec eax
+	jnz lp128encsingle
+
+end_enc128:
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	
+	ret
+
+
+align 16
+global _iEnc128_CTR
+_iEnc128_CTR:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov	eax,[ecx+12]
+	movdqu xmm5,[eax]	;initial counter
+
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_encctr128
+	
+	cmp eax,4
+	jl lp128encctrsingle
+
+	test	ecx,0xf
+	jz		lpencctr128four
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	mov ecx,esp	
+
+
+	align 16	
+	
+lpencctr128four:
+	
+	test eax,eax
+	jz end_encctr128
+	
+	cmp eax,4
+	jl lp128encsingle
+
+	load_and_inc4 [ecx+0*16]
+	add esi,4*16
+	aesenc4	[ecx+1*16]
+	aesenc4	[ecx+2*16]
+	aesenc4	[ecx+3*16]
+	aesenc4	[ecx+4*16]
+	aesenc4	[ecx+5*16]
+	aesenc4	[ecx+6*16]
+	aesenc4	[ecx+7*16]
+	aesenc4	[ecx+8*16]
+	aesenc4	[ecx+9*16]
+	aesenclast4	[ecx+10*16]
+	xor_with_input4 esi-(4*16)
+	
+	store4 esi+edi-16*4
+	sub eax,4
+	jmp lpencctr128four
+	
+	align 16
+lp128encctrsingle:
+
+	movdqa	xmm0,xmm5
+	paddq	xmm5,[counter_add_one]
+	add esi, 16
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1_u [ecx+1*16]
+	aesenc1_u [ecx+2*16]
+	aesenc1_u [ecx+3*16]
+	aesenc1_u [ecx+4*16]     
+	aesenc1_u [ecx+5*16]
+	aesenc1_u [ecx+6*16]
+	aesenc1_u [ecx+7*16]
+	aesenc1_u [ecx+8*16]
+	aesenc1_u [ecx+9*16]
+	aesenclast1_u [ecx+10*16]
+	movdqu xmm4, [esi-16]
+	pxor	xmm0,xmm4
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	dec eax
+	jnz lp128encctrsingle
+
+end_encctr128:
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+
+	mov ecx,[esp-4+8]  ; first arg
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm5 ; store last counter for chaining
+	
+	ret
+
+
+align 16
+global _iEnc192_CTR
+_iEnc192_CTR:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov	eax,[ecx+12]
+	movdqu xmm5,[eax]	;initial counter
+
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_encctr192
+	
+	cmp eax,4
+	jl lp192encctrsingle
+
+	test	ecx,0xf
+	jz		lpencctr128four
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	mov ecx,esp	
+
+
+	align 16	
+	
+lpencctr192four:
+	
+	test eax,eax
+	jz end_encctr192
+	
+	cmp eax,4
+	jl lp192encsingle
+
+	load_and_inc4 [ecx+0*16]
+	add esi,4*16
+	aesenc4	[ecx+1*16]
+	aesenc4	[ecx+2*16]
+	aesenc4	[ecx+3*16]
+	aesenc4	[ecx+4*16]
+	aesenc4	[ecx+5*16]
+	aesenc4	[ecx+6*16]
+	aesenc4	[ecx+7*16]
+	aesenc4	[ecx+8*16]
+	aesenc4	[ecx+9*16]
+	aesenc4	[ecx+10*16]
+	aesenc4	[ecx+11*16]
+	aesenclast4	[ecx+12*16]
+	xor_with_input4 esi-(4*16)
+	
+	store4 esi+edi-16*4
+	sub eax,4
+	jmp lpencctr192four
+	
+	align 16
+lp192encctrsingle:
+
+	movdqa	xmm0,xmm5
+	paddq	xmm5,[counter_add_one]
+	add esi, 16
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1_u  [ecx+1*16]
+	aesenc1_u  [ecx+2*16]
+	aesenc1_u  [ecx+3*16]
+	aesenc1_u  [ecx+4*16]     
+	aesenc1_u  [ecx+5*16]
+	aesenc1_u  [ecx+6*16]
+	aesenc1_u  [ecx+7*16]
+	aesenc1_u  [ecx+8*16]
+	aesenc1_u  [ecx+9*16]
+	aesenc1_u  [ecx+10*16]
+	aesenc1_u  [ecx+11*16]
+	aesenclast1_u  [ecx+12*16]
+	movdqu xmm4, [esi-16]
+	pxor	xmm0,xmm4
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	dec eax
+	jnz lp192encctrsingle
+
+end_encctr192:
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+
+	mov ecx,[esp-4+8]  ; first arg
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm5 ; store last counter for chaining
+	
+	ret
+
+
+align 16
+global _iEnc256_CTR
+_iEnc256_CTR:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov	eax,[ecx+12]
+	movdqu xmm5,[eax]	;initial counter
+
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_encctr256
+	
+	cmp eax,4
+	jl lp256encctrsingle
+
+	test	ecx,0xf
+	jz		lpencctr128four
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	copy_round_keys esp,ecx,13
+	copy_round_keys esp,ecx,14
+	mov ecx,esp	
+
+
+	align 16	
+	
+lpencctr256four:
+	
+	test eax,eax
+	jz end_encctr256
+	
+	cmp eax,4
+	jl lp256encctrsingle
+
+	load_and_inc4 [ecx+0*16]
+	add esi,4*16
+	aesenc4	[ecx+1*16]
+	aesenc4	[ecx+2*16]
+	aesenc4	[ecx+3*16]
+	aesenc4	[ecx+4*16]
+	aesenc4	[ecx+5*16]
+	aesenc4	[ecx+6*16]
+	aesenc4	[ecx+7*16]
+	aesenc4	[ecx+8*16]
+	aesenc4	[ecx+9*16]
+	aesenc4	[ecx+10*16]
+	aesenc4	[ecx+11*16]
+	aesenc4	[ecx+12*16]
+	aesenc4	[ecx+13*16]
+	aesenclast4	[ecx+14*16]
+	xor_with_input4 esi-(4*16)
+	
+	store4 esi+edi-16*4
+	sub eax,4
+	jmp lpencctr256four
+	
+	align 16
+	
+lp256encctrsingle:
+
+	movdqa	xmm0,xmm5
+	paddq	xmm5,[counter_add_one]
+	add esi, 16
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1_u  [ecx+1*16]
+	aesenc1_u  [ecx+2*16]
+	aesenc1_u  [ecx+3*16]
+	aesenc1_u  [ecx+4*16]     
+	aesenc1_u  [ecx+5*16]
+	aesenc1_u  [ecx+6*16]
+	aesenc1_u  [ecx+7*16]
+	aesenc1_u  [ecx+8*16]
+	aesenc1_u  [ecx+9*16]
+	aesenc1_u  [ecx+10*16]
+	aesenc1_u  [ecx+11*16]
+	aesenc1_u  [ecx+12*16]
+	aesenc1_u  [ecx+13*16]
+	aesenclast1_u  [ecx+14*16]
+	movdqu xmm4, [esi-16]
+	pxor	xmm0,xmm4
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	dec eax
+	jnz lp256encctrsingle
+
+end_encctr256:
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+
+	mov ecx,[esp-4+8]  ; first arg
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm5 ; store last counter for chaining
+	
+	ret
+
+
+
+
+
+
+align 16
+global _iEnc128_CBC
+_iEnc128_CBC:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov	eax,[ecx+12]
+	movdqu xmm1,[eax]	;iv	
+	
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	sub edi,esi
+
+	test	ecx,0xf
+	jz		lp128encsingle_CBC
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	mov ecx,esp	
+
+	align 16	
+	
+lp128encsingle_CBC:
+
+	movdqu xmm0, [esi]
+	add esi, 16
+	pxor xmm0, xmm1
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1  [ecx+1*16]
+	aesenc1  [ecx+2*16]
+	aesenc1  [ecx+3*16]
+	aesenc1  [ecx+4*16]     
+	aesenc1  [ecx+5*16]
+	aesenc1  [ecx+6*16]
+	aesenc1  [ecx+7*16]
+	aesenc1  [ecx+8*16]
+	aesenc1  [ecx+9*16]
+	aesenclast1  [ecx+10*16]
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	movdqa xmm1,xmm0
+	dec eax
+	jnz lp128encsingle_CBC
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	mov ecx,[esp-4+8]  ; first arg
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm1 ; store last iv for chaining
+	
+	ret
+
+
+align 16
+global _iEnc192_CBC
+_iEnc192_CBC:
+	mov ecx,[esp-4+8]  ; first arg
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov	eax,[ecx+12]
+	movdqu xmm1,[eax]	;iv	
+	
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	sub edi,esi
+
+	test	ecx,0xf
+	jz		lp192encsingle_CBC
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	mov ecx,esp	
+
+	align 16	
+	
+lp192encsingle_CBC:
+
+	movdqu xmm0, [esi]
+	add esi, 16
+	pxor xmm0, xmm1
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1  [ecx+1*16]
+	aesenc1  [ecx+2*16]
+	aesenc1  [ecx+3*16]
+	aesenc1  [ecx+4*16]     
+	aesenc1  [ecx+5*16]
+	aesenc1  [ecx+6*16]
+	aesenc1  [ecx+7*16]
+	aesenc1  [ecx+8*16]
+	aesenc1  [ecx+9*16]
+	aesenc1  [ecx+10*16]
+	aesenc1  [ecx+11*16]
+	aesenclast1  [ecx+12*16]
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	movdqa xmm1,xmm0
+	dec eax
+	jnz lp192encsingle_CBC
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	mov ecx,[esp-4+8]  ; first arg
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm1 ; store last iv for chaining
+	
+	ret
+
+align 16
+global _iEnc256_CBC
+_iEnc256_CBC:
+	mov ecx,[esp-4+8]  ; first arg
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov	eax,[ecx+12]
+	movdqu xmm1,[eax]	;iv	
+	
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	sub edi,esi
+
+	test	ecx,0xf
+	jz		lp256encsingle_CBC
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	copy_round_keys esp,ecx,13
+	copy_round_keys esp,ecx,14
+	mov ecx,esp	
+
+	align 16	
+	
+lp256encsingle_CBC:
+
+;abab
+	movdqu xmm0, [esi]
+	add esi, 16
+	pxor xmm0, xmm1
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1 [ecx+1*16]
+	aesenc1 [ecx+2*16]
+	aesenc1 [ecx+3*16]
+	aesenc1 [ecx+4*16]     
+	aesenc1 [ecx+5*16]
+	aesenc1 [ecx+6*16]
+	aesenc1 [ecx+7*16]
+	aesenc1 [ecx+8*16]
+	aesenc1 [ecx+9*16]
+	aesenc1 [ecx+10*16]
+	aesenc1 [ecx+11*16]
+	aesenc1 [ecx+12*16]
+	aesenc1 [ecx+13*16]
+	aesenclast1 [ecx+14*16]
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	movdqa xmm1,xmm0
+	dec eax
+	jnz lp256encsingle_CBC
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	mov ecx,[esp-4+8]
+	mov ecx,[ecx+12]
+	movdqu	[ecx],xmm1 ; store last iv for chaining
+	
+	ret
+
+
+
+
+
+align 16
+global _iEnc192
+_iEnc192:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi
+
+	test eax,eax
+	jz end_enc192
+	
+	cmp eax,4
+	jl lp192encsingle
+
+	test	ecx,0xf
+	jz		lpenc192four
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	mov ecx,esp	
+
+	align 16	
+	
+lpenc192four:
+	
+	test eax,eax
+	jz end_enc192
+	
+	cmp eax,4
+	jl lp192encsingle
+
+	load_and_xor4 esi,[ecx+0*16]
+	add esi,4*16
+	aesenc4	[ecx+1*16]
+	aesenc4	[ecx+2*16]
+	aesenc4	[ecx+3*16]
+	aesenc4	[ecx+4*16]
+	aesenc4	[ecx+5*16]
+	aesenc4	[ecx+6*16]
+	aesenc4	[ecx+7*16]
+	aesenc4	[ecx+8*16]
+	aesenc4	[ecx+9*16]
+	aesenc4	[ecx+10*16]
+	aesenc4	[ecx+11*16]
+	aesenclast4	[ecx+12*16]
+	
+	store4 esi+edi-16*4
+	sub eax,4
+	jmp lpenc192four
+	
+	align 16
+lp192encsingle:
+
+	movdqu xmm0, [esi]
+	add esi, 16
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1_u [ecx+1*16]
+	aesenc1_u [ecx+2*16]
+	aesenc1_u [ecx+3*16]
+	aesenc1_u [ecx+4*16]     
+	aesenc1_u [ecx+5*16]
+	aesenc1_u [ecx+6*16]
+	aesenc1_u [ecx+7*16]
+	aesenc1_u [ecx+8*16]
+	aesenc1_u [ecx+9*16]
+	aesenc1_u [ecx+10*16]
+	aesenc1_u [ecx+11*16]
+	aesenclast1_u [ecx+12*16]
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	dec eax
+	jnz lp192encsingle
+
+end_enc192:
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	
+	ret
+
+
+
+
+align 16
+global _iEnc256
+_iEnc256:
+	mov ecx,[esp-4+8]
+	
+	push esi
+	push edi
+	push ebp
+	mov ebp,esp
+	
+	sub esp,16*16
+	and esp,0xfffffff0
+
+	mov eax,[ecx+16] ; numblocks
+	mov esi,[ecx]
+	mov edi,[ecx+4]
+	mov ecx,[ecx+8]
+	
+	sub edi,esi	
+
+	test eax,eax
+	jz end_enc256
+
+	cmp eax,4
+	jl lp256enc
+
+	test	ecx,0xf
+	jz	lp256enc4
+	
+	copy_round_keys esp,ecx,0
+	copy_round_keys esp,ecx,1
+	copy_round_keys esp,ecx,2
+	copy_round_keys esp,ecx,3
+	copy_round_keys esp,ecx,4
+	copy_round_keys esp,ecx,5
+	copy_round_keys esp,ecx,6
+	copy_round_keys esp,ecx,7
+	copy_round_keys esp,ecx,8
+	copy_round_keys esp,ecx,9
+	copy_round_keys esp,ecx,10
+	copy_round_keys esp,ecx,11
+	copy_round_keys esp,ecx,12
+	copy_round_keys esp,ecx,13
+	copy_round_keys esp,ecx,14
+	mov ecx,esp	
+
+
+
+	align 16
+	
+lp256enc4:
+	test eax,eax
+	jz end_enc256
+
+	cmp eax,4
+	jl lp256enc
+
+
+	load_and_xor4 esi,[ecx+0*16]
+	add esi, 16*4
+	aesenc4 [ecx+1*16]
+	aesenc4 [ecx+2*16]
+	aesenc4 [ecx+3*16]
+	aesenc4 [ecx+4*16]
+	aesenc4 [ecx+5*16]
+	aesenc4 [ecx+6*16]
+	aesenc4 [ecx+7*16]
+	aesenc4 [ecx+8*16]
+	aesenc4 [ecx+9*16]
+	aesenc4 [ecx+10*16]
+	aesenc4 [ecx+11*16]
+	aesenc4 [ecx+12*16]
+	aesenc4 [ecx+13*16]
+	aesenclast4 [ecx+14*16]
+
+	store4  esi+edi-16*4
+	sub eax,4
+	jmp lp256enc4
+	
+	align 16
+lp256enc:
+
+	movdqu xmm0, [esi]
+	add esi, 16
+	movdqu xmm4,[ecx+0*16]
+	pxor xmm0, xmm4
+	aesenc1_u [ecx+1*16]
+	aesenc1_u [ecx+2*16]
+	aesenc1_u [ecx+3*16]
+	aesenc1_u [ecx+4*16]
+	aesenc1_u [ecx+5*16]
+	aesenc1_u [ecx+6*16]
+	aesenc1_u [ecx+7*16]
+	aesenc1_u [ecx+8*16]
+	aesenc1_u [ecx+9*16]
+	aesenc1_u [ecx+10*16]
+	aesenc1_u [ecx+11*16]
+	aesenc1_u [ecx+12*16]
+	aesenc1_u [ecx+13*16]
+	aesenclast1_u [ecx+14*16]
+
+		; Store output encrypted data into CIPHERTEXT array
+	movdqu  [esi+edi-16], xmm0
+	dec eax
+	jnz lp256enc
+
+end_enc256:
+
+
+	mov esp,ebp
+	pop ebp
+	pop edi
+	pop esi
+	
+	ret
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/include/iaes_asm_interface.h view
@@ -0,0 +1,126 @@+/* 
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice, 
+ *       this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Intel Corporation nor the names of its contributors 
+ *       may be used to endorse or promote products derived from this software 
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 _INTEL_AES_ASM_INTERFACE_H__
+#define _INTEL_AES_ASM_INTERFACE_H__
+
+
+#include "iaesni.h"
+
+
+
+//structure to pass aes processing data to asm level functions
+typedef struct _sAesData
+{
+	_AES_IN		UCHAR	*in_block;
+	_AES_OUT	UCHAR	*out_block;
+	_AES_IN		UCHAR	*expanded_key;		
+	_AES_INOUT	UCHAR	*iv;					// for CBC mode
+	_AES_IN		size_t	num_blocks;
+} sAesData;
+
+#if (__cplusplus)
+extern "C"
+{
+#endif
+#if 0
+#define MYSTDCALL __stdcall
+#else
+#define MYSTDCALL 
+#endif
+
+#if defined __linux__ || defined __APPLE__
+#ifndef __LP64__
+#define iEncExpandKey256 _iEncExpandKey256
+#define iEncExpandKey192 _iEncExpandKey192
+#define iEncExpandKey128 _iEncExpandKey128
+#define iDecExpandKey256 _iDecExpandKey256
+#define iDecExpandKey192 _iDecExpandKey192
+#define iDecExpandKey128 _iDecExpandKey128
+#define iEnc128 _iEnc128
+#define iDec128 _iDec128
+#define iEnc256 _iEnc256
+#define iDec256 _iDec256
+#define iEnc192 _iEnc192
+#define iDec192 _iDec192
+#define iEnc128_CBC _iEnc128_CBC
+#define iDec128_CBC _iDec128_CBC
+#define iEnc256_CBC _iEnc256_CBC
+#define iDec256_CBC _iDec256_CBC
+#define iEnc192_CBC _iEnc192_CBC
+#define iDec192_CBC _iDec192_CBC
+#define iEnc128_CTR _iEnc128_CTR
+#define iEnc192_CTR _iEnc192_CTR
+#define iEnc256_CTR _iEnc256_CTR
+#define do_rdtsc    _do_rdtsc
+#endif // lp64
+#endif // linux
+	// prepearing the different key rounds, for enc/dec in asm
+	// expnaded key should be 16-byte aligned
+	// expanded key should have enough space to hold all key rounds (16 bytes per round) - 256 bytes would cover all cases (AES256 has 14 rounds + 1 xor)
+	void MYSTDCALL iEncExpandKey256(_AES_IN UCHAR *key, _AES_OUT UCHAR *expanded_key);
+	void MYSTDCALL iEncExpandKey192(_AES_IN UCHAR *key, _AES_OUT UCHAR *expanded_key);
+	void MYSTDCALL iEncExpandKey128(_AES_IN UCHAR *key, _AES_OUT UCHAR *expanded_key);
+
+	void MYSTDCALL iDecExpandKey256(UCHAR *key, _AES_OUT UCHAR *expanded_key);
+	void MYSTDCALL iDecExpandKey192(UCHAR *key, _AES_OUT UCHAR *expanded_key);
+	void MYSTDCALL iDecExpandKey128(UCHAR *key, _AES_OUT UCHAR *expanded_key);
+
+
+	//enc/dec asm functions
+	void MYSTDCALL iEnc128(sAesData *data);
+	void MYSTDCALL iDec128(sAesData *data);
+	void MYSTDCALL iEnc256(sAesData *data);
+	void MYSTDCALL iDec256(sAesData *data);
+	void MYSTDCALL iEnc192(sAesData *data);
+	void MYSTDCALL iDec192(sAesData *data);
+
+	void MYSTDCALL iEnc128_CBC(sAesData *data);
+	void MYSTDCALL iDec128_CBC(sAesData *data);
+	void MYSTDCALL iEnc256_CBC(sAesData *data);
+	void MYSTDCALL iDec256_CBC(sAesData *data);
+	void MYSTDCALL iEnc192_CBC(sAesData *data);
+	void MYSTDCALL iDec192_CBC(sAesData *data);
+
+
+	void MYSTDCALL iEnc128_CTR(sAesData *data);
+	void MYSTDCALL iEnc256_CTR(sAesData *data);
+	void MYSTDCALL iEnc192_CTR(sAesData *data);
+
+	// rdtsc function
+	unsigned long long do_rdtsc(void);
+
+
+#if (__cplusplus)
+}
+#endif
+
+
+#endif
+
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/include/iaesni.h view
@@ -0,0 +1,151 @@+/* 
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice, 
+ *       this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Intel Corporation nor the names of its contributors 
+ *       may be used to endorse or promote products derived from this software 
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 _IAESNI_H__
+#define _IAESNI_H__
+
+#include <stdlib.h>
+
+#define AES_INSTRCTIONS_CPUID_BIT (1<<25)
+
+//indicates input param
+#define _AES_IN	
+
+//indicates output param
+#define _AES_OUT
+
+//indicates input/output param - based on context
+#define _AES_INOUT
+
+typedef unsigned char UCHAR;
+
+
+#ifndef bool
+#define bool BOOL
+#endif
+//test if the processor actually supports the above functions
+//executing one the functions below without processor support will cause UD fault
+//bool check_for_aes_instructions(void);
+#if (__cplusplus)
+extern "C" {
+#endif
+int check_for_aes_instructions(void);
+
+#define ROUND_KEYS_UNALIGNED_TESTING
+
+#if defined __linux__ || defined __APPLE__
+
+#warning "Configuring for Linux or Darwin"
+
+#ifdef ROUND_KEYS_UNALIGNED_TESTING
+
+#define DEFINE_ROUND_KEYS \
+	UCHAR __attribute__ ((aligned (16))) _expandedKey[16*16];	\
+	UCHAR *expandedKey = _expandedKey + 4;	\
+
+
+#else
+
+
+
+#define DEFINE_ROUND_KEYS \
+	UCHAR __attribute__ ((aligned (16))) _expandedKey[16*16];	\
+	UCHAR *expandedKey = _expandedKey;	\
+
+#endif
+
+#else // if not __linux__
+
+#warning "Configuring for Windows..."
+
+#ifdef ROUND_KEYS_UNALIGNED_TESTING
+
+#define DEFINE_ROUND_KEYS \
+	__declspec(align(16)) UCHAR _expandedKey[16*16];	\
+	UCHAR *expandedKey = _expandedKey + 4;	\
+
+
+#else
+
+
+
+#define DEFINE_ROUND_KEYS \
+	__declspec(align(16)) UCHAR _expandedKey[16*16];	\
+	UCHAR *expandedKey = _expandedKey;	\
+
+
+#endif
+
+#endif
+
+
+
+// encryption functions
+// plainText is pointer to input stream
+// cipherText is pointer to buffer to be filled with encrypted (cipher text) data
+// key is pointer to enc key (sizes are 16 bytes for AES-128, 24 bytes for AES-192, 32 for AES-256)
+// numBlocks is number of 16 bytes blocks to process - note that encryption is done of full 16 byte blocks
+void intel_AES_enc128(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_enc192(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_enc256(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+
+
+void intel_AES_enc128_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_enc192_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_enc256_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+
+
+// encryption functions
+// cipherText is pointer to encrypted stream
+// plainText is pointer to buffer to be filled with original (plain text) data
+// key is pointer to enc key (sizes are 16 bytes for AES-128, 24 bytes for AES-192, 32 for AES-256)
+// numBlocks is number of 16 bytes blocks to process - note that decryption is done of full 16 byte blocks
+void intel_AES_dec128(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_dec192(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+void intel_AES_dec256(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);
+
+void intel_AES_dec128_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_dec192_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+void intel_AES_dec256_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);
+
+void intel_AES_encdec128_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+void intel_AES_encdec192_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+void intel_AES_encdec256_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);
+
+
+#if (__cplusplus)
+}
+#endif
+
+
+#endif
+
+
+
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/mk_lnx_lib.sh view
@@ -0,0 +1,43 @@+#!/bin/bash++# arg in required. Must be 86 (for 32bit compiler) or 64 (for 64bit compiler)+arch=$1+if [ "x$arch" != "x86" ]; then +   if [ "x$arch" != "x64" ]; then +      echo "One arg in required. Must be 86 (for 32bit compiler) or 64 (for 64bit compiler)"+      exit 1+   fi+fi+if [ "$arch" == "86" ]; then +sz=32+fi+if [ "$arch" == "64" ]; then +sz=64+fi+#echo got sz= $sz and arch= $arch++mkdir -p obj/x${arch}++#yasm="../yasm/yasm"+yasm=yasm++pushd .+asm="iaesx${arch} do_rdtsc"+for i in $asm; do +   # echo do $i.s+   echo "$yasm -D__linux__ -g dwarf2 -f elf${sz} asm/x${arch}/$i.s -o obj/x${arch}/$i.o"+   $yasm -D__linux__ -g dwarf2 -f elf${sz} asm/x${arch}/$i.s -o obj/x${arch}/$i.o+done+# gcc -O3 -g -m${sz} -Iinclude/ -c src/intel_aes.c -o obj/x${arch}/intel_aes.o+# RRN: Building a shared library too:+ echo "Compiling C source"+ gcc -fPIC -O3 -g -Iinclude/ -c src/intel_aes.c -o obj/x64/intel_aes.o++ echo "Linking static and dynamic libraries"+ ar -r lib/x${arch}/libintel_aes${arch}.a obj/x${arch}/*.o+ gcc -shared -dynamic  -o lib/x${arch}/libintel_aes${arch}.so obj/x64/*.o+popd++echo "Copying to cbits parent directory"+cp lib/x${arch}/*.so ../../+cp lib/x${arch}/*.a  ../../
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/mk_win_lib.bat view
@@ -0,0 +1,35 @@+
+@rem arg in required. Must be 86 (for 32bit compiler) or 64 (for 64bit compiler)
+SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
+set arch=%1
+if "%arch%" == "86" goto OK
+if "%arch%" == "64" goto OK
+echo One arg in required. Must be 86 (for 32bit compiler) or 64 (for 64bit compiler)
+goto :ERR
+
+:OK
+if "%arch%" == "86" set sz=32
+if "%arch%" == "64" set sz=64
+
+mkdir obj\x%arch%
+
+set yasm=..\yasm\yasm-0.8.0-win%sz%.exe
+
+%yasm% -f win%sz% asm\x%arch%\do_rdtsc.s -o obj\x%arch%\do_rdtsc.obj
+
+pushd .
+set asm=iaesx%arch%
+for %%i in (%asm%) do (
+	%yasm% -f win%sz% asm/x%arch%/%%i.s -o obj/x%arch%/%%i.obj
+	if ERRORLEVEL 1 goto :ERR
+)
+cl /O2 /Zi -Iinclude\ -c src\intel_aes.c /Foobj\x%arch%\intel_aes.obj
+if ERRORLEVEL 1 goto :ERR
+lib /out:lib\x%arch%\intel_aes%arch%.lib obj\x%arch%\*.obj
+if ERRORLEVEL 1 goto :ERR
+popd
+
+goto :EOF
+
+:ERR
+echo got an error in mk_win_lib.bat
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/aessample.c view
@@ -0,0 +1,302 @@+/* 
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice, 
+ *       this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Intel Corporation nor the names of its contributors 
+ *       may be used to endorse or promote products derived from this software 
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 <stdlib.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <memory.h>
+#ifdef __linux__
+#include <alloca.h>
+#ifndef _alloca
+#define _alloca alloca
+#endif
+#endif
+
+#include "iaesni.h"
+
+// test vectors from fips-197 Appendix C http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+
+unsigned char test_plain_text[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
+unsigned char test_cipher_text_128[16] = {0x69,0xc4,0xe0,0xd8,0x6a,0x7b,0x04,0x30,0xd8,0xcd,0xb7,0x80,0x70,0xb4,0xc5,0x5a};
+unsigned char test_cipher_text_192[16] = {0xdd,0xa9,0x7c,0xa4,0x86,0x4c,0xdf,0xe0,0x6e,0xaf,0x70,0xa0,0xec,0x0d,0x71,0x91};
+unsigned char test_cipher_text_256[16] = {0x8e,0xa2,0xb7,0xca,0x51,0x67,0x45,0xbf,0xea,0xfc,0x49,0x90,0x4b,0x49,0x60,0x89};
+unsigned char test_key_128[16] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
+unsigned char test_key_192[24] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17};
+unsigned char test_key_256[32] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f};
+unsigned char test_iv[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
+
+
+#define TEST_PASS (0)
+#define TEST_FAIL_ENC (1)
+#define TEST_FAIL_DEC (2)
+
+int test128(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc128(testVector,testResult,test_key_128,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testResult[i] != test_cipher_text_128[i % 16])
+			return TEST_FAIL_ENC;
+
+		testVector[i] = 0xdd;
+	}
+
+	intel_AES_dec128(testResult,testVector,test_key_128,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return TEST_PASS;
+
+}
+
+
+int test128_CBC(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	UCHAR local_test_iv[16];
+	unsigned int half_size;
+
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	memcpy(local_test_iv,test_iv,16);
+	intel_AES_enc128_CBC(testVector,testResult,test_key_128,numBlocks,local_test_iv);
+
+	//test chaining as well
+	memcpy(local_test_iv,test_iv,16);
+	half_size = numBlocks/2;
+	intel_AES_dec128_CBC(testResult,testVector,test_key_128,half_size,local_test_iv);
+	intel_AES_dec128_CBC(testResult+16*(half_size),testVector+16*(half_size),test_key_128,numBlocks - half_size,local_test_iv);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+		{
+			printf("%d",i);
+			return TEST_FAIL_DEC;
+		}
+	}
+
+	return TEST_PASS;
+
+}
+
+
+
+
+int test192(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc192(testVector,testResult,test_key_192,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testResult[i] != test_cipher_text_192[i % 16])
+			return TEST_FAIL_ENC;
+
+		testVector[i] = 0xdd;
+	}
+
+	intel_AES_dec192(testResult,testVector,test_key_192,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return 0;
+
+}
+
+
+int test192_CBC(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	UCHAR local_test_iv[16];
+	unsigned int half_size;
+
+	memcpy(local_test_iv,test_iv,16);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc192_CBC(testVector,testResult,test_key_128,numBlocks,local_test_iv);
+
+
+	memcpy(local_test_iv,test_iv,16);
+	half_size = numBlocks/2;
+	intel_AES_dec192_CBC(testResult,testVector,test_key_128,half_size,local_test_iv);
+	intel_AES_dec192_CBC(testResult+16*(half_size),testVector+16*(half_size),test_key_128,numBlocks - half_size,local_test_iv);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return TEST_PASS;
+
+}
+
+
+int test256(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc256(testVector,testResult,test_key_256,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testResult[i] != test_cipher_text_256[i % 16])
+			return TEST_FAIL_ENC;
+
+		testVector[i] = 0xdd;
+	}
+
+	intel_AES_dec256(testResult,testVector,test_key_256,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return 0;
+
+}
+
+
+int test256_CBC(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	UCHAR local_test_iv[16];
+	unsigned int half_size = numBlocks/2;
+
+	memcpy(local_test_iv,test_iv,16);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc256_CBC(testVector,testResult,test_key_256,numBlocks,local_test_iv);
+
+
+	memcpy(local_test_iv,test_iv,16);
+	intel_AES_dec256_CBC(testResult,testVector,test_key_256,half_size,local_test_iv);
+	intel_AES_dec256_CBC(testResult+16*(half_size),testVector+16*(half_size),test_key_256,numBlocks - half_size,local_test_iv);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return TEST_PASS;
+
+}
+
+
+int  main(void)
+{
+	int i;
+
+	if (check_for_aes_instructions() == 0)
+	{
+		printf("no AES instructions detected! - stopping the test app\n");
+		return 1;
+	}
+
+	printf("AES instructions detected\n");
+	for (i=1;i<4096;i+=i*3/2)
+	{
+		printf("testing %d blocks,AES-128: %s",i,(test128(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf(",AES-192: %s",(test192(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf(",AES-256: %s",(test256(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf("\n");
+	}
+
+	for (i=1;i<4096;i+=i*3/2)
+	{
+		printf("testing %d blocks,AES-128-CBC: %s",i,(test128_CBC(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf(",AES-192-CBC: %s",(test192_CBC(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf(",AES-256-CBC: %s\n",(test256_CBC(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf("\n");
+	}
+	return 0;
+}
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/aessampletiming.cpp view
@@ -0,0 +1,541 @@+/* 
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice, 
+ *       this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Intel Corporation nor the names of its contributors 
+ *       may be used to endorse or promote products derived from this software 
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ * 
+*/
+
+/* 
+	This program can take a long time to run and it may use the whole system.
+	The program gets timing info for various sizes, methods, and number of threads.
+	It also raises the priority of the timing threads to reduce the variation in performance.
+	It has windows specific code and I haven't ported it to linux.
+	See aes_gladman_subset\src\modetest.c for example implementation in linux and windows
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <memory.h>
+#include "iaesni.h"
+#include <windows.h>
+
+// test vectors from fips-197 Appendix C http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+
+unsigned char test_plain_text[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
+unsigned char test_cipher_text_128[16] = {0x69,0xc4,0xe0,0xd8,0x6a,0x7b,0x04,0x30,0xd8,0xcd,0xb7,0x80,0x70,0xb4,0xc5,0x5a};
+unsigned char test_cipher_text_192[16] = {0xdd,0xa9,0x7c,0xa4,0x86,0x4c,0xdf,0xe0,0x6e,0xaf,0x70,0xa0,0xec,0x0d,0x71,0x91};
+unsigned char test_cipher_text_256[16] = {0x8e,0xa2,0xb7,0xca,0x51,0x67,0x45,0xbf,0xea,0xfc,0x49,0x90,0x4b,0x49,0x60,0x89};
+unsigned char test_key_128[16] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
+unsigned char test_key_192[24] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17};
+unsigned char test_key_256[32] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f};
+unsigned char test_iv[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
+
+SYSTEM_INFO si;
+
+
+#define TEST_PASS (0)
+#define TEST_FAIL_ENC (1)
+#define TEST_FAIL_DEC (2)
+
+int test128(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc128(testVector,testResult,test_key_128,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testResult[i] != test_cipher_text_128[i % 16])
+			return TEST_FAIL_ENC;
+
+		testVector[i] = 0xdd;
+	}
+
+	intel_AES_dec128(testResult,testVector,test_key_128,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return TEST_PASS;
+
+}
+
+
+int test128_CBC(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	UCHAR local_test_iv[16];
+
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	memcpy(local_test_iv,test_iv,16);
+	intel_AES_enc128_CBC(testVector,testResult,test_key_128,numBlocks,local_test_iv);
+
+	//test chaining as well
+	memcpy(local_test_iv,test_iv,16);
+	unsigned int half_size = numBlocks/2;
+	intel_AES_dec128_CBC(testResult,testVector,test_key_128,half_size,local_test_iv);
+	intel_AES_dec128_CBC(testResult+16*(half_size),testVector+16*(half_size),test_key_128,numBlocks - half_size,local_test_iv);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+		{
+			printf("%d",i);
+			return TEST_FAIL_DEC;
+		}
+	}
+
+	return TEST_PASS;
+
+}
+
+
+
+
+int test192(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc192(testVector,testResult,test_key_192,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testResult[i] != test_cipher_text_192[i % 16])
+			return TEST_FAIL_ENC;
+
+		testVector[i] = 0xdd;
+	}
+
+	intel_AES_dec192(testResult,testVector,test_key_192,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return 0;
+
+}
+
+
+int test192_CBC(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	UCHAR local_test_iv[16];
+
+	memcpy(local_test_iv,test_iv,16);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc192_CBC(testVector,testResult,test_key_128,numBlocks,local_test_iv);
+
+
+	memcpy(local_test_iv,test_iv,16);
+	unsigned int half_size = numBlocks/2;
+	intel_AES_dec192_CBC(testResult,testVector,test_key_128,half_size,local_test_iv);
+	intel_AES_dec192_CBC(testResult+16*(half_size),testVector+16*(half_size),test_key_128,numBlocks - half_size,local_test_iv);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return TEST_PASS;
+
+}
+
+
+int test256(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc256(testVector,testResult,test_key_256,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testResult[i] != test_cipher_text_256[i % 16])
+			return TEST_FAIL_ENC;
+
+		testVector[i] = 0xdd;
+	}
+
+	intel_AES_dec256(testResult,testVector,test_key_256,numBlocks);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return 0;
+
+}
+
+
+int test256_CBC(unsigned long numBlocks)
+{
+	unsigned int buffer_size = numBlocks*16;
+	unsigned int i;
+	UCHAR *testVector = (UCHAR*)_alloca(buffer_size);
+	UCHAR *testResult = (UCHAR*)_alloca(buffer_size);
+	UCHAR local_test_iv[16];
+
+	memcpy(local_test_iv,test_iv,16);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		testVector[i] = test_plain_text[i % 16];
+		testResult[i] = 0xee;
+	}
+
+	intel_AES_enc256_CBC(testVector,testResult,test_key_128,numBlocks,local_test_iv);
+
+
+	memcpy(local_test_iv,test_iv,16);
+	unsigned int half_size = numBlocks/2;
+	intel_AES_dec256_CBC(testResult,testVector,test_key_128,half_size,local_test_iv);
+	intel_AES_dec256_CBC(testResult+16*(half_size),testVector+16*(half_size),test_key_128,numBlocks - half_size,local_test_iv);
+
+	for (i=0;i<buffer_size;i++)
+	{
+		if (testVector[i] != test_plain_text[i % 16])
+			return TEST_FAIL_DEC;
+	}
+
+	return TEST_PASS;
+
+}
+
+#define MAX_NUM_THREADS (16)
+#define ITER 30000
+
+#include "iaes_asm_interface.h"
+
+typedef 	void (__cdecl *AESPROC)(sAesData *);
+typedef 	void (__cdecl *KEYGENPROC)(UCHAR *key,UCHAR *round_keys);
+
+struct ThreadCommad;
+DWORD __stdcall ThreadFunction(ThreadCommad *cmd);
+
+
+
+struct ThreadCommad
+{
+	volatile LONG *start_mutex;
+	volatile LONG *end_mutex;
+	UINT num_threads;
+	UINT thread_num;
+	UINT num_iterations;
+	void (__cdecl *proc)(sAesData *);
+	KEYGENPROC key_gen_proc;
+	sAesData data;
+	UCHAR *key;
+	double avg_clocks;
+	char padd[256];
+};
+
+struct TestCfg
+{
+	UINT num_threads;
+	UINT buffer_size;
+	UINT alignment;
+	KEYGENPROC key_gen_proc;
+	AESPROC proc;
+	bool in_place;
+	bool aligned_round_keys;
+	char *name;
+};
+
+TestCfg cfg[] = {
+//	{1,2048,4096,iEncExpandKey256,iEnc256,false,true,"Enc-ECB-256"},
+//	{1,2048,4096,iEncExpandKey192,iEnc192,false,true,"Enc-ECB-192"},
+//	{1,2048,4096,iEncExpandKey128,iEnc128,false,true,"Enc-ECB-128"},
+	
+	{1,2048,4096,iEncExpandKey256,iEnc256_CBC,false,true,"Enc-CBC-256"},
+	{1,2048,4096,iEncExpandKey192,iEnc192_CBC,false,true,"Enc-CBC-192"},
+	{1,2048,4096,iEncExpandKey128,iEnc128_CBC,false,true,"Enc-CBC-128"},
+
+//	{1,2048,4096,iDecExpandKey256,iDec256,false,true,"Dec-ECB-256"},
+//	{1,2048,4096,iDecExpandKey192,iDec192,false,true,"Dec-ECB-192"},
+//	{1,2048,4096,iDecExpandKey128,iDec128,false,true,"Dec-ECB-128"},
+	
+	{1,2048,4096,iDecExpandKey256,iDec256_CBC,false,true,"Dec-CBC-256"},
+	{1,2048,4096,iDecExpandKey192,iDec192_CBC,false,true,"Dec-CBC-192"},
+	{1,2048,4096,iDecExpandKey128,iDec128_CBC,false,true,"Dec-CBC-128"},
+
+};
+
+struct TestCommand
+{
+	LONG start_mutex;
+	char pad1[256];
+	LONG end_mutex;
+	char pad2[256];
+
+	UCHAR iv[16];
+
+	UCHAR round_keys_buf[17*16];
+	bool in_place;
+	UINT num_threads;
+
+	ThreadCommad cmds[MAX_NUM_THREADS];
+
+	void BuildTest(TestCfg *cfg)
+	{
+		UCHAR key[16];
+		UINT i;
+		UINT block_size = ((cfg->buffer_size + 15)/16)*16;
+		num_threads = cfg->num_threads;
+		start_mutex = end_mutex = 0;
+		UCHAR *round_keys = round_keys_buf;
+		in_place = cfg->in_place;
+
+		if (cfg->aligned_round_keys && ((DWORD_PTR)round_keys & 0xf) != 0)
+		{
+			*(DWORD_PTR *)&round_keys += 15;
+			*(DWORD_PTR *)&round_keys /= 16;
+			*(DWORD_PTR *)&round_keys *= 16;
+		}
+		else if (!cfg->aligned_round_keys && ((DWORD_PTR)round_keys & 0xf) == 0)
+		{
+			*(DWORD_PTR *)&round_keys += 15;
+			*(DWORD_PTR *)&round_keys /= 16;
+			*(DWORD_PTR *)&round_keys *= 16;
+			*(DWORD_PTR *)&round_keys += 4;
+		}
+
+		cfg->key_gen_proc(key,round_keys);
+		
+		for (i=0;i<num_threads;i++)
+		{
+			cmds[i].data.in_block = (UCHAR *)_aligned_malloc(block_size,cfg->alignment);
+			if (!in_place) cmds[i].data.out_block = (UCHAR *)_aligned_malloc(block_size,cfg->alignment);
+			cmds[i].num_iterations = ITER;
+			cmds[i].num_threads = num_threads;
+			cmds[i].thread_num = i;
+			cmds[i].proc = cfg->proc;
+			cmds[i].start_mutex = &start_mutex;
+			cmds[i].end_mutex = &end_mutex;
+			cmds[i].data.iv = iv;
+			cmds[i].data.expanded_key = round_keys;
+			cmds[i].data.num_blocks = block_size/16;
+			cmds[i].key_gen_proc = cfg->key_gen_proc;
+			cmds[i].key = (UCHAR *)key;
+		}
+	}
+
+	void ExecuteTest(double *min,double *max,double *avg)
+	{
+		HANDLE *h = new HANDLE[num_threads];
+		UINT i;
+
+		for (i=0;i<num_threads;i++)
+		{
+			h[i] = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)ThreadFunction,&cmds[i],0,NULL);
+		}
+		WaitForMultipleObjects(num_threads,h,TRUE,INFINITE);
+
+		double amin = 1e38,amax = 0,sum = 0;
+		for (i=0;i<num_threads;i++)
+		{
+			if (cmds[i].avg_clocks < amin) amin = cmds[i].avg_clocks;
+			if (cmds[i].avg_clocks > amax) amax = cmds[i].avg_clocks;
+			sum += cmds[i].avg_clocks;
+		}
+
+		sum /= num_threads;
+
+		*min = amin;
+		*max = amax;
+		*avg = sum;
+
+		delete[] h;
+
+	}
+
+	void FreeTest()
+	{
+		UINT i;
+		for (i=0;i<num_threads;i++)
+		{
+			_aligned_free(cmds[i].data.in_block);
+			if (!in_place) _aligned_free(cmds[i].data.out_block);
+		}
+		
+	}
+
+
+};
+
+
+DWORD __stdcall ThreadFunction(ThreadCommad *cmd)
+{
+	UINT i;
+	if (cmd->num_threads != si.dwNumberOfProcessors)
+		SetThreadAffinityMask(GetCurrentThread(),1<<(cmd->thread_num*2));
+	else
+		SetThreadAffinityMask(GetCurrentThread(),1<<(cmd->thread_num));
+
+
+	SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL );
+	Sleep(10);
+	InterlockedIncrement(cmd->start_mutex);
+	while(*cmd->start_mutex < cmd->num_threads);
+	cmd->key_gen_proc(cmd->key,cmd->data.expanded_key);
+	cmd->proc(&cmd->data);
+	unsigned __int64 start = do_rdtsc();
+	for (i=0;i<cmd->num_iterations;i++)
+	{
+		cmd->key_gen_proc(cmd->key,cmd->data.expanded_key);
+		cmd->proc(&cmd->data);
+	}
+	unsigned __int64 stop = do_rdtsc() - start;
+	InterlockedIncrement(cmd->end_mutex);
+	while(*cmd->end_mutex < cmd->num_threads);
+	cmd->avg_clocks = (double)stop/(double)cmd->num_iterations;
+	return 0;
+}
+
+
+
+
+UINT test_threads[] = {1,2,4,6,12};
+
+
+void main()
+{
+	int i;
+
+	fprintf(stderr, "This program can take a long time to run and it may use the whole system.\n");
+	fprintf(stderr, "The program gets timing info for various sizes, methods, and number of threads.\n");
+	fprintf(stderr, "It also raises the priority of the timing threads to reduce the variation in performance.\n");
+	if (!check_for_aes_instructions())
+	{
+		printf("no AES instructions detected! - stopping the test app\n");
+		return;
+	}
+
+	printf("AES instructions detected\n");
+
+#if 0
+	for (i=1;i<4096;i+=i*3/2)
+	{
+		printf("testing %d blocks,AES-128: %s",i,(test128(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf(",AES-192: %s",(test192(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf(",AES-256: %s",(test256(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf("\n");
+	}
+
+	for (i=1;i<4096;i+=i*3/2)
+	{
+		printf("testing %d blocks,AES-128-CBC: %s",i,(test128_CBC(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf(",AES-192-CBC: %s",(test192_CBC(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf(",AES-256-CBC: %s\n",(test256_CBC(i) != TEST_PASS) ? "FAIL" : "PASS");
+		printf("\n");
+	}
+#endif
+
+	TestCommand cmd;
+	UINT nthr;
+	UINT buffsize;
+
+	GetSystemInfo(&si);
+
+	printf("#threads,#bytes,");
+	for (i=0;i<sizeof(cfg)/sizeof(TestCfg);i++)
+		printf("%s,,,",cfg[i].name);
+	printf("\n");
+	printf(",,");
+	for (i=0;i<sizeof(cfg)/sizeof(TestCfg);i++)
+		printf("min,max,avg,",cfg[i].name);
+	printf("\n");
+
+	for (nthr = 0;nthr < sizeof(test_threads)/sizeof(UINT);nthr++)
+	{
+		if (test_threads[nthr] > si.dwNumberOfProcessors) continue;
+
+		for (buffsize = 16;buffsize < 32*1024;buffsize +=(buffsize/2048 + 1)*16)
+		{
+
+			for (i=0;i<sizeof(cfg)/sizeof(TestCfg);i++)
+			{
+				double min,max,avg;
+				cfg[i].buffer_size = buffsize;
+				cfg[i].num_threads = test_threads[nthr];
+				if (i == 0) 			printf("%d,%d,",cfg[i].num_threads,cfg[i].buffer_size);
+				cmd.BuildTest(&cfg[i]);
+				cmd.ExecuteTest(&min,&max,&avg);
+				printf("%lf,%lf,%lf,",min/buffsize,max/buffsize,avg/buffsize);
+				cmd.FreeTest();
+			}
+			printf("\n");
+		}
+	}
+
+}
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/intel_aes.c view
@@ -0,0 +1,308 @@+/* 
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice, 
+ *       this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Intel Corporation nor the names of its contributors 
+ *       may be used to endorse or promote products derived from this software 
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ * 
+*/
+
+#if (__cplusplus)
+extern "C" {
+#endif
+
+#include "iaesni.h"
+#include "iaes_asm_interface.h"
+
+#if (__cplusplus)
+}
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+
+
+void intel_AES_enc128(UCHAR *plainText,UCHAR *cipherText,UCHAR *key,size_t numBlocks)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = plainText;
+	aesData.out_block = cipherText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+
+	iEncExpandKey128(key,expandedKey);
+	iEnc128(&aesData);
+}
+
+
+void intel_AES_enc128_CBC(UCHAR *plainText,UCHAR *cipherText,UCHAR *key,size_t numBlocks,UCHAR *iv)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = plainText;
+	aesData.out_block = cipherText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = iv;
+
+	iEncExpandKey128(key,expandedKey);
+	iEnc128_CBC(&aesData);
+}
+
+
+void intel_AES_enc192(UCHAR *plainText,UCHAR *cipherText,UCHAR *key,size_t numBlocks)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = plainText;
+	aesData.out_block = cipherText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+
+	iEncExpandKey192(key,expandedKey);
+	iEnc192(&aesData);
+}
+
+
+void intel_AES_enc192_CBC(UCHAR *plainText,UCHAR *cipherText,UCHAR *key,size_t numBlocks,UCHAR *iv)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = plainText;
+	aesData.out_block = cipherText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = iv;
+
+	iEncExpandKey192(key,expandedKey);
+	iEnc192_CBC(&aesData);
+}
+
+
+void intel_AES_enc256(UCHAR *plainText,UCHAR *cipherText,UCHAR *key,size_t numBlocks)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = plainText;
+	aesData.out_block = cipherText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+
+	iEncExpandKey256(key,expandedKey);
+	iEnc256(&aesData);
+}
+
+
+void intel_AES_enc256_CBC(UCHAR *plainText,UCHAR *cipherText,UCHAR *key,size_t numBlocks,UCHAR *iv)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = plainText;
+	aesData.out_block = cipherText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = iv;
+
+	iEncExpandKey256(key,expandedKey);
+	iEnc256_CBC(&aesData);
+}
+
+
+void intel_AES_dec128(UCHAR *cipherText,UCHAR *plainText,UCHAR *key,size_t numBlocks)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = cipherText;
+	aesData.out_block = plainText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+
+	iDecExpandKey128(key,expandedKey);
+	iDec128(&aesData);
+}
+
+void intel_AES_dec128_CBC(UCHAR *cipherText,UCHAR *plainText,UCHAR *key,size_t numBlocks,UCHAR *iv)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = cipherText;
+	aesData.out_block = plainText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = iv;
+
+	iDecExpandKey128(key,expandedKey);
+	iDec128_CBC(&aesData);
+}
+
+
+void intel_AES_dec192(UCHAR *cipherText,UCHAR *plainText,UCHAR *key,size_t numBlocks)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = cipherText;
+	aesData.out_block = plainText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+
+	iDecExpandKey192(key,expandedKey);
+	iDec192(&aesData);
+}
+
+
+void intel_AES_dec192_CBC(UCHAR *cipherText,UCHAR *plainText,UCHAR *key,size_t numBlocks,UCHAR *iv)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = cipherText;
+	aesData.out_block = plainText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = iv;
+
+	iDecExpandKey192(key,expandedKey);
+	iDec192_CBC(&aesData);
+}
+
+
+void intel_AES_dec256(UCHAR *cipherText,UCHAR *plainText,UCHAR *key,size_t numBlocks)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = cipherText;
+	aesData.out_block = plainText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+
+	iDecExpandKey256(key,expandedKey);
+	iDec256(&aesData);
+}
+
+
+void intel_AES_dec256_CBC(UCHAR *cipherText,UCHAR *plainText,UCHAR *key,size_t numBlocks,UCHAR *iv)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = cipherText;
+	aesData.out_block = plainText;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = iv;
+
+	iDecExpandKey256(key,expandedKey);
+	iDec256_CBC(&aesData);
+}
+
+
+
+void intel_AES_encdec256_CTR(UCHAR *in,UCHAR *out,UCHAR *key,size_t numBlocks,UCHAR *ic)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = in;
+	aesData.out_block = out;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = ic;
+
+	iEncExpandKey256(key,expandedKey);
+	iEnc256_CTR(&aesData);
+}
+
+void intel_AES_encdec192_CTR(UCHAR *in,UCHAR *out,UCHAR *key,size_t numBlocks,UCHAR *ic)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = in;
+	aesData.out_block = out;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = ic;
+
+	iEncExpandKey192(key,expandedKey);
+	iEnc192_CTR(&aesData);
+}
+
+void intel_AES_encdec128_CTR(UCHAR *in,UCHAR *out,UCHAR *key,size_t numBlocks,UCHAR *ic)
+{
+	DEFINE_ROUND_KEYS
+	sAesData aesData;
+	aesData.in_block = in;
+	aesData.out_block = out;
+	aesData.expanded_key = expandedKey;
+	aesData.num_blocks = numBlocks;
+	aesData.iv = ic;
+
+	iEncExpandKey128(key,expandedKey);
+	iEnc128_CTR(&aesData);
+}
+
+
+
+#if defined __linux__ || defined __APPLE__ 
+static void __cpuid(unsigned int where[4], unsigned int leaf) {
+  asm volatile("cpuid":"=a"(*where),"=b"(*(where+1)), "=c"(*(where+2)),"=d"(*(where+3)):"a"(leaf));
+  return;
+}
+#else // windows
+#include <intrin.h>
+#endif
+
+/* 
+ * check_for_aes_instructions()
+ *   return 1 if support AES-NI and 0 if don't support AES-NI
+ */
+
+int check_for_aes_instructions()
+{
+	unsigned int cpuid_results[4];
+	int yes=1, no=0;
+
+	__cpuid(cpuid_results,0);
+
+	if (cpuid_results[0] < 1)
+		return no;
+/*
+ *      MSB         LSB
+ * EBX = 'u' 'n' 'e' 'G'
+ * EDX = 'I' 'e' 'n' 'i'
+ * ECX = 'l' 'e' 't' 'n'
+ */
+	
+	if (memcmp((unsigned char *)&cpuid_results[1], "Genu", 4) != 0 ||
+		memcmp((unsigned char *)&cpuid_results[3], "ineI", 4) != 0 ||
+		memcmp((unsigned char *)&cpuid_results[2], "ntel", 4) != 0)
+		return no;
+
+	__cpuid(cpuid_results,1);
+
+	if (cpuid_results[2] & AES_INSTRCTIONS_CPUID_BIT)
+		return yes;
+
+	return no;
+}
+
+
+
+ cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_license.txt view
@@ -0,0 +1,34 @@+/* intel_aes_lib source files come from Intel.
+ * Modified by Patrick Fay
+ *
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+      this list of conditions and the following disclaimer.
+    * 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.
+    * Neither the name of Intel Corporation nor the names of its contributors 
+      may be used to endorse or promote products derived from this software 
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+ ---------------------------------------------------------------------------
+ Issue Date: Aug 6, 2010
+ */
+
+Other source code files use the license shown in the source code file.
+ cbits/Makefile view
@@ -0,0 +1,9 @@++++all:+	cd Intel_AESNI_Sample_Library_v1.0/intel_aes_lib; $(MAKE)++clean:+	cd Intel_AESNI_Sample_Library_v1.0/intel_aes_lib; $(MAKE) clean+	rm -f libintel_aes.a libintel_aes.so
+ cbits/c_test.c view
@@ -0,0 +1,55 @@++++#include <stdio.h>+#include <stdlib.h>++// Haskell can call this with a memory location.+// void blast_rands(int* ptr1, int* ptr2)+void blast_rands(int count, int* ptr)+{+  int i;+  for(i=0; i<count; i++)+  {+    *ptr = rand();+  }+}++void store_loop(int count, volatile int* ptr)+{+  int i;+  for(i=0; i<count; i++)+  {+    *ptr += 1;+  }+}+++#if 0+// On a 3.33ghz desktop nehalem this produces 100M rands in 0.826 seconds.+int main() {++  int i, sum = 0; +  for(i=0; i<100000000; i++) +  {+    sum += rand();+  }++  printf("Sum of 100M randoms: %d\n", sum);++  return 0;+}+#endif++++// [2011.01.30] TEMP, testing AES bindings+#if 0+#include "iaesni.h"++void temp_test128()+{+   printf("  Inside C test...\n");+   +}+#endif
+ cbits/gladman/aes.h view
@@ -0,0 +1,205 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+
+ This file contains the definitions required to use AES in C. See aesopt.h
+ for optimisation details.
+*/
+
+#ifndef _AES_H
+#define _AES_H
+
+#include <stdlib.h>
+
+/*  This include is used to find 8 & 32 bit unsigned integer types  */
+#include "brg_types.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+#define AES_128     /* if a fast 128 bit key scheduler is needed    */
+#define AES_192     /* if a fast 192 bit key scheduler is needed    */
+#define AES_256     /* if a fast 256 bit key scheduler is needed    */
+#define AES_VAR     /* if variable key size scheduler is needed     */
+#define AES_MODES   /* if support is needed for modes               */
+
+/* The following must also be set in assembler files if being used  */
+
+#define AES_ENCRYPT /* if support for encryption is needed          */
+#define AES_DECRYPT /* if support for decryption is needed          */
+#define AES_REV_DKS /* define to reverse decryption key schedule    */
+
+#define AES_BLOCK_SIZE  16  /* the AES block size in bytes          */
+#define N_COLS           4  /* the number of columns in the state   */
+
+/* The key schedule length is 11, 13 or 15 16-byte blocks for 128,  */
+/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes  */
+/* or 44, 52 or 60 32-bit words.                                    */
+
+#if defined( AES_VAR ) || defined( AES_256 )
+#define KS_LENGTH       60
+#elif defined( AES_192 )
+#define KS_LENGTH       52
+#else
+#define KS_LENGTH       44
+#endif
+
+#define AES_RETURN INT_RETURN
+
+/* the character array 'inf' in the following structures is used    */
+/* to hold AES context information. This AES code uses cx->inf.b[0] */
+/* to hold the number of rounds multiplied by 16. The other three   */
+/* elements can be used by code that implements additional modes    */
+
+typedef union
+{   uint_32t l;
+    uint_8t b[4];
+} aes_inf;
+
+typedef struct
+{   uint_32t ks[KS_LENGTH];
+    aes_inf inf;
+} aes_encrypt_ctx;
+
+typedef struct
+{   uint_32t ks[KS_LENGTH];
+    aes_inf inf;
+} aes_decrypt_ctx;
+
+/* This routine must be called before first use if non-static       */
+/* tables are being used                                            */
+
+AES_RETURN aes_init(void);
+
+/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */
+/* those in the range 128 <= key_len <= 256 are given in bits       */
+
+#if defined( AES_ENCRYPT )
+
+#if defined( AES_128 ) || defined( AES_VAR)
+AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]);
+#endif
+
+#if defined( AES_192 ) || defined( AES_VAR)
+AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]);
+#endif
+
+#if defined( AES_256 ) || defined( AES_VAR)
+AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]);
+#endif
+
+#if defined( AES_VAR )
+AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]);
+#endif
+
+AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]);
+
+#endif
+
+#if defined( AES_DECRYPT )
+
+#if defined( AES_128 ) || defined( AES_VAR)
+AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]);
+#endif
+
+#if defined( AES_192 ) || defined( AES_VAR)
+AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]);
+#endif
+
+#if defined( AES_256 ) || defined( AES_VAR)
+AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]);
+#endif
+
+#if defined( AES_VAR )
+AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]);
+#endif
+
+AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]);
+
+#endif
+
+#if defined( AES_MODES )
+
+/* Multiple calls to the following subroutines for multiple block   */
+/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */
+/* long messages incremantally provided that the context AND the iv */
+/* are preserved between all such calls.  For the ECB and CBC modes */
+/* each individual call within a series of incremental calls must   */
+/* process only full blocks (i.e. len must be a multiple of 16) but */
+/* the CFB, OFB and CTR mode calls can handle multiple incremental  */
+/* calls of any length. Each mode is reset when a new AES key is    */
+/* set but ECB and CBC operations can be reset without setting a    */
+/* new key by setting a new IV value.  To reset CFB, OFB and CTR    */
+/* without setting the key, aes_mode_reset() must be called and the */
+/* IV must be set.  NOTE: All these calls update the IV on exit so  */
+/* this has to be reset if a new operation with the same IV as the  */
+/* previous one is required (or decryption follows encryption with  */
+/* the same IV array).                                              */
+
+AES_RETURN aes_test_alignment_detection(unsigned int n);
+
+AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, const aes_encrypt_ctx cx[1]);
+
+AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, const aes_decrypt_ctx cx[1]);
+
+AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, const aes_encrypt_ctx cx[1]);
+
+AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, const aes_decrypt_ctx cx[1]);
+
+AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]);
+
+AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx cx[1]);
+
+AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx cx[1]);
+
+#define aes_ofb_encrypt aes_ofb_crypt
+#define aes_ofb_decrypt aes_ofb_crypt
+
+AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx cx[1]);
+
+typedef void cbuf_inc(unsigned char *cbuf);
+
+#define aes_ctr_encrypt aes_ctr_crypt
+#define aes_ctr_decrypt aes_ctr_crypt
+
+AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,
+            int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]);
+
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+ cbits/gladman/aes.txt view
@@ -0,0 +1,556 @@+
+An AES (Rijndael) Implementation in C/C++ (as specified in FIPS-197)
+====================================================================
+
+Changes in this Version (16/04/2007)
+====================================
+
+These changes remove errors in the VC++ build files and add some 
+improvements in file naming consitency and portability. There are
+no changes to overcome reported bugs in the code.
+
+1. gen_tabs() has been renamed to aes_init() to better decribe its
+   function to those not familiar with AES internals.
+
+2. via_ace.h has been renamed to aes_via_ace.h.
+
+3. Minor changes have been made to aestab.h and aestab.c to enable
+   all the code to be compiled in either C or C++.
+   
+4. The code for detecting memory alignment in aesmdoes.c has been
+   simplified and a new routine has been added:
+   
+       aes_test_alignment_detection()
+   
+   to check that the aligment test is likely to be correct.
+
+5. The addition of support for Structured Exception Handling (SEH) 
+   to YASM (well done Peter and Michael!) has allowed the AMD64 
+   x64 assembler code to be changed to comply with SEH requriements.
+       
+6. Corrections to build files (for win32 debug build).
+
+Overview
+========
+
+This code implements AES for both 32 and 64 bit systems with optional
+assembler support for x86 and AMD64/EM64T (but optimised for AMD64).
+
+The basic AES source code files are as follows:
+
+aes.h           the header file needed to use AES in C
+aescpp.h        the header file required with to use AES in C++
+aesopt.h        the header file for setting options (and some common code)
+aestab.h        the header file for the AES table declaration
+aescrypt.c      the main C source code file for encryption and decryption
+aeskey.c        the main C source code file for the key schedule
+aestab.c        the main file for the AES tables
+brg_types.h     a header defining some standard types and DLL defines
+brg_endian.h    a header containing code to detect or define endianness
+aes_x86_v1.asm  x86 assembler (YASM) alternative to aescrypt.c using
+                large tables
+aes_x86_v2.asm  x86 assembler (YASM) alternative to aescrypt.c using
+                compressed tables
+aes_amd64.asm   AMD64 assembler (YASM) alternative to aescrypt.c using
+                compressed tables
+
+In addition AES modes are implemented in the files:
+
+aes_modes.c     AES modes with optional support for VIA ACE detection and use
+aes_via_ace.h   the header file for VIA ACE support
+
+Other associated files for testing and support are:
+
+aesaux.h        header for auxilliary routines for testsing
+aesaux.c        auxilliary routines for testsingt
+aestst.h        header file for setting the testing environment
+rdtsc.h         a header file that provides access to the Time Stamp Counter
+aestst.c        a simple test program for quick tests of the AES code
+aesgav.c        a program to generate and verify the test vector files
+aesrav.c        a program to verify output against the test vector files
+aestmr.c        a program to time the code on x86 systems
+modetest.c      a program to test the AES modes support
+vbxam.doc       a demonstration of AES DLL use from Visual Basic in Microsoft Word
+vb.txt          Visual Basic code from the above example (win32 only)
+aesxam.c        an example of AES use
+tablegen.c      a program to generate a simplified 'aestab.c' file for
+                use with compilers that find aestab.c too complex
+yasm.rules      the YASM build rules file for Microsoft Visual Studio 2005
+via_ace.txt     describes support for the VIA ACE cryptography engine
+aes.txt         this file
+
+Building The AES Libraries
+--------------------------
+
+A. Versions
+-----------
+
+The code can be used to build static and dynamic libraries, each in five
+versions:
+
+    C           uses C source code only
+    ASM_X86_V1C large table x86 assembler code for encrypt/decrypt
+    ASM_X86_V2  compressed table x86 assembler for encrypt/decrypt and keying
+    ASM_X86_V2C compressed table x86 assembler code for encrypt/decrypt
+    ASM_AMD64   compressed table x86 assembler code for encrypt/decrypt
+
+The C version can be compiled for Win32 or x64, the x86 assembler versions
+are for Win32 only and the AMD64 version for x64 only.
+
+B. Types
+--------
+
+The code makes use of types defined as uint_<nn>t where <nn> is the length
+of the type, for example, the unsigned 32-bit type is 'uint_32t'.  These are
+NOT the same as the fixed width integer types in C99, inttypes.h and stdint.h
+since several attempts to use these types have shown that support for them is
+still highly variable.  But a regular expression search and replace in VC++
+with search on 'uint_{:z}t' and a replace with 'uint\1_t' will convert these
+types to C99 types (there should be similar search/replace facilities on other
+systems).
+
+C. YASM
+-------
+
+If you wish to use the x86 assembler files you will also need the YASM open
+source x86 assembler (r1331 or later) for Windows which can be obtained from:
+
+  http://www.tortall.net/projects/yasm/
+
+This assembler should be placed in the bin directory used by VC++, which, for
+Visual Stduio 2005, is typically:
+
+ C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin
+
+You will also need to move the yasm.rules file from this distribution into
+the directory where Visual Studio 2005 expects to find it, which is typically:
+
+ C:\Program Files (x86)\Microsoft Visual Studio 8\VC\VCProjectDefaults
+
+Alternatively you can configure the path for rules files within Visual Studio.
+
+D. Configuration
+----------------
+
+The following configurations are available as projects for Visual Studio 2005
+but the following descriptions should allow them to be built in other x86
+environments:
+
+    lib_generic_c       Win32 and x64
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aescrypt.c, aeskey.c, aestab.c, aes_modes.c
+        defines
+    dll_generic_c       Win32 and x64
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aescrypt.c, aeskey.c, aestab.c, aes_modes.c
+        defines         DLL_EXPORT
+
+    lib_asm_x86_v1c     Win32
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aeskey.c, aestab.c, aes_modes.c
+        x86 assembler:  aes_x86_v1.asm
+        defines         ASM_X86_V1C (set for C and assembler files)
+    dll_asm_x86_v1c     Win32
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aeskey.c, aestab.c, aes_modes.c
+        x86 assembler:  aes_x86_v1.asm
+        defines         DLL_EXPORT, ASM_X86_V1C (set for C and assembler files)
+
+    lib_asm_x86_v2c     Win32
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aeskey.c, aestab.c, aes_modes.c
+        x86 assembler:  aes_x86_v2.asm
+        defines         ASM_X86_V2C (set for C and assembler files)
+    dll_asm_x86_v2c     Win32
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aeskey.c, aestab.c, aes_modes.c
+        x86 assembler:  aes_x86_v1.asm
+        defines         DLL_EXPORT, ASM_X86_V2C (set for C and assembler files)
+
+    lib_asm_x86_v2      Win32
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aes_modes.c
+        x86 assembler:  aes_x86_v1.asm
+        defines         ASM_X86_V2 (set for C and assembler files)
+    dll_asm_x86_v2      Win32
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aes_modes.c
+        x86 assembler:  aes_x86_v1.asm
+        defines         DLL_EXPORT, ASM_AMD64_C (set for C and assembler files)
+
+    lib_asm_amd64_c     x64
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aes_modes.c
+        x86 assembler:  aes_amd64.asm
+        defines         ASM_X86_V2 (set for C and assembler files)
+    dll_asm_amd64_c     x64
+        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h
+        C source:       aes_modes.c
+        x86 assembler:  aes_amd64.asm
+        defines         DLL_EXPORT, ASM_AMD64_C (set for C and assembler files)
+
+Notes:
+
+ASM_X86_V1C is defined if using the version 1 assembler code (aescrypt1.asm).
+            The defines in the assember file must match those in aes.h and
+            aesopt.h).  Also remember to include/exclude the right assembler
+            and C files in the build to avoid undefined or multiply defined
+            symbols - include aescrypt1.asm and exclude aescrypt.c and
+            aescrypt2.asm.
+
+ASM_X86_V2  is defined if using the version 2 assembler code (aescrypt2.asm).
+            This version provides a full, self contained assembler version
+            and does not use any C source code files except for the mutiple
+            block encryption modes that are provided by aes_modes.c. The define
+            ASM_X86_V2 must be set on the YASM command line (or in aescrypt2.asm)
+            to use this version and all C files except aec_modes.c and. for the
+            DLL build, aestab.c must be excluded from the build.
+
+ASM_X86_V2C is defined when using the version 2 assembler code (aescrypt2.asm)
+            with faster key scheduling provided by the in C code (the options in
+            the assember file must match those in aes.h and aesopt.h).  In this
+            case aeskey.c and aestab.c are needed with aescrypt2.asm and the
+            define ASM_X86_V2C must be set for both the C files and for
+            asecrypt2.asm command lines (or in aesopt.h and aescrypt2.asm).
+            Include aescrypt2.asm aeskey.c and aestab.c, exclude aescrypt.c for
+            this option.
+
+ASM_AMD64_C is defined when using the AMD64 assembly code because the C key
+            scheduling is sued in this case.
+
+DLL_EXPORT  must be defined to generate the DLL version of the code and
+            to run tests on it
+
+DLL_IMPORT  must be defined to use the DLL version of the code in an
+            application program
+
+Directories the paths for the various directories for test vector input and
+            output have to be set in aestst.h
+
+VIA ACE     see the via_ace.txt for this item
+
+Static      The static libraries are named:
+Libraries
+                aes_lib_generic_c.lib
+                aes_lib_asm_x86_v1c.lib
+                aes_lib_asm_x86_v2.lib
+                aes_lib_asm_x86_v2c.lib
+                aes_lib_asm_amd64_c.lib
+
+            and placed in one of the the directories:
+
+                lib\win32\release\
+                lib\win32\debug\
+                lib\x64\release\
+                lib\x64\debug\
+
+            in the aes root directory depending on the platform(win32 or
+            x64) and the build (release or debug). After any of these is
+            built it is then copied into aes.lib, which is the library
+            that is subsequently used for testing. Hence testing is for
+            the last static library built.
+
+Dynamic     The static libraries are named:
+Libraries
+                aes_lib_generic_c.dll
+                aes_lib_asm_x86_v1c.dll
+                aes_lib_asm_x86_v2.dll
+                aes_lib_asm_x86_v2c.dll
+                aes_lib_asm_amd64_c.dll
+
+            and placed in one of the the directories:
+
+                dll\win32\release\
+                dll\win32\debug\
+                dll\x64\release\
+                dll\x64\debug\
+
+            in the aes root directory depending on the platform(win32 or
+            x64) and the build (release or debug).  Each DLL library:
+
+                aes_<ext>.dll
+
+            has three associated files:
+
+                aes_dll_<ext>.lib   the library file for implicit linking
+                aes_dll_<ext>.exp   the exports file
+                aes_dll_<ext>.pdb   the symbol file
+
+            After any DLL is built it and its three related files are then
+            copied into aes.lib, aes.lib, aes,exp and aes.pdb, which are
+            the libraries used for testing.  Hence testing is for the last
+            static library or DLL built.
+
+E. Testing
+----------
+
+These tests require that the test vector files are placed in the 'testvals' 
+subdirectory. If the AES Algorithm Validation Suite tests will be use3d then
+the *.fax files need to be put in the 'testvals\fax' subdirectory.  This is
+covered in more detail below.
+
+The projects test_dll and time_dll are used to test and time the last DLL
+built.  These use the files:
+
+    test_dll:       Win32 (x64 for the C and AMD64 versions)
+        headers:    aes.h, aescpp.h, brg_types.h, aesaux.h and aestst.h
+        C source:   aesaux.c, aesrav.c
+        defines:    DLL_IMPORT
+
+    time_dll:       Win32 (x64 for the C and AMD64 versions)
+        headers:    aes.h, aescpp.h, brg_types.h, aesaux.h aestst.h and rdtsc.h
+        C source:   aesaux.c, aestmr.c
+        defines:    DLL_IMPORT
+
+and link to the DLL using explicit linking. However, if the lib file associated
+with the DLL is linked into this project and the symbol DYNAMIC_LINK in aestst.h
+is left undefined, then implicit linking will be used
+
+The projects test_lib and time_lib are used to test and time the last static LIB
+built. They use the files:
+
+    test_lib:       Win32 (x64 for the C and AMD64 versions)
+        headers:    aes.h, aescpp.h, brg_types.h, aesaux.h and aestst.h
+        C source:   aesaux.c, aesrav.c
+        defines:
+
+    time_lib:       Win32 (x64 for the C and AMD64 versions)
+        headers:    aes.h, aescpp.h, brg_types.h, aesaux.h, aestst.h and rdtsc.h
+        C source:   aesaux.c, aestmr.c
+        defines:
+
+and link to the last static library built.
+
+The above test take command line arguments that determine which test are run
+as follows:
+
+    test_lib /t:[knec] /k:[468]
+    test_dll /t:[knec] /k:[468]
+
+where the symbols in square brackets can be used in any combination (without
+the brackets) and have the following meanings:
+
+        /t:[knec]   selects which tests are used
+        /k:[468]    selects the key lengths used
+        /c          compares output with reference (see later)
+
+        k: generate ECB Known Answer Test files
+        n: generate ECB Known Answer Test files (new)
+        e: generate ECB Monte Carlo Test files
+        c: generate CBC Monte Carlo Test files
+
+and the characters giving the lengths are digits representing the lengths in
+32-bit units.\n\n");
+
+The project test_modes tests the AES modes.  It uses the files:
+
+    test_modes:     Win32 or x64
+        headers:    aes.h, aescpp.h, brg_types.h, aesaux,h and aestst.h
+        C source:   aesaux.c, modetest.c
+        defines:    none for static library test, DLL_IMPORT for DLL test
+
+which again links to the last library built.
+
+F. Other Applications
+---------------------
+
+These are:
+
+    gen_tests       builds the test_vector files. The commad line is
+                        gen_tests /t:knec /k:468 /c
+                    as described earlier
+                    
+    test_aes_avs    run the AES Algorithm Validation Suite tests for
+                    ECB, CBC, CFB and OFB modes
+
+    gen_tables      builds a simple version of aes_tab.c (in aestab2.c)
+                    for compilers that cannot handle the normal version
+    aes_example     provides an example of AES use
+
+These applications are linked to the last static library built or, if
+DLL_IMPORT is defined during compilation, to the last DLL built.
+
+G. Use of the VIA ACE Cryptography Engine
+-----------------------------------------
+
+The use of the code with the VIA ACE cryptography engine in described in the
+file via_ace.txt. In outline aes_modes.c is used and USE_VIA_ACE_IF_PRESENT
+is defined either in section 2 of aesopt.h or as a compilation option in Visual
+Studio. If in addition ASSUME_VIA_ACE_PRESENT is also defined then all normal
+AES code will be removed if not needed to support VIA ACE use.  If VIA ACE
+support is needed and AES assembler is being used only the ASM_X86_V1C and
+ASM_X86_V2C versions should be used since ASM_X86_V2 and ASM_AMD64 do not
+support the VIA ACE engine.
+
+H. The AES Test Vector Files
+----------------------------
+
+These files fall in the following groups (where <nn> is a two digit
+number):
+
+1. ecbvk<nn>.txt  ECB vectors with variable key
+2. ecbvt<nn>.txt  ECB vectors with variable text
+3. ecbnk<nn>.txt  new ECB vectors with variable key
+4. ecbnt<nn>.txt  new ECB vectors with variable text
+5. ecbme<nn>.txt  ECB monte carlo encryption test vectors
+6. ecbmd<nn>.txt  ECB monte carlo decryption test vectors
+7. cbcme<nn>.txt  CBC monte carlo encryption test vectors
+8. cbcmd<nn>.txt  CBC monte carlo decryption test vectors
+
+The first digit of the numeric suffix on the filename gives the block size
+in 32 bit units and the second numeric digit gives the key size. For example,
+the file ecbvk44.txt provides the test vectors for ECB encryption with a 128
+bit block size and a 128 bit key size. The test routines expect to find these
+files in the 'testvals' subdirectory within the aes root directory. The
+'outvals' subdirectory is used for outputs that are compared with the files
+in 'testvals'. Note that the monte carlo test vectors are the result of
+applying AES iteratively 10000 times, not just once.
+
+The AES Algorithm Validation Suite tests can be run for ECB, CBC, CFB and 
+OFB modes (CFB1 and CFB8 are not implemented).  The test routine uses the 
+*.fax test files, which should be placed in the 'testvals\fax' subdirectory.
+
+I. The Basic AES Calling Interface
+----------------------------------
+
+The basic AES code keeps its state in a context, there being different 
+contexts for encryption and decryption:
+
+    aes_encrypt_ctx
+    aes_decrypt_ctx
+    
+The AES code is initialised with the call
+
+	aes_init(void)
+	
+although this is only essential if the option to generate the AES tables at 
+run-time has been set in the options (i.e.fixed tables are not being used).
+    
+The AES encryption key is set by one of the calls:
+ 
+    aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1])
+    aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1])
+    aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1])
+
+or by:
+
+    aes_encrypt_key(const unsigned char *key, int key_len, 
+                                                aes_encrypt_ctx cx[1])
+
+where the key length is set by 'key_len', which can be the length in bits 
+or bytes.  
+
+Similarly, the AES decryption key is set by one of:
+
+    aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1])
+    aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1])
+    aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1])
+
+or by:
+
+    aes_decrypt_key(const unsigned char *key, int key_len, 
+                                                aes_decrypt_ctx cx[1])
+ 
+Encryption and decryption for a single 16 byte block is then achieved using:
+
+    aes_encrypt(const unsigned char *in, unsigned char *out, 
+                                            const aes_encrypt_ctx cx[1])
+    aes_decrypt(const unsigned char *in, unsigned char *out, 
+                                            const aes_decrypt_ctx cx[1])
+                                            
+The above subroutines return a value of EXIT_SUCCESS or EXIT_FAILURE 
+depending on whether the operation succeeded or failed.
+ 
+J. The Calling Interface for the AES Modes
+------------------------------------------
+
+The subroutines for the AES modes, ECB, CBC, CFB, OFB and CTR, each process
+blocks of variable length and can also be called several times to complete 
+single mode operations incrementally on long messages (or those messages,
+not all of which are available at the same time).  The calls:
+
+    aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, const aes_encrypt_ctx cx[1])
+
+    aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, const aes_decrypt_ctx cx[1])
+
+for ECB operations and those for CBC:
+
+    aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, const aes_encrypt_ctx cx[1])
+
+    aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, const aes_decrypt_ctx cx[1])
+ 
+can only process blocks whose lengths are multiples of 16 bytes but the calls 
+for CFB, OFB and CTR mode operations:
+
+    aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx cx[1])
+
+    aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx cx[1])
+
+    aes_ofb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx cx[1])
+
+    aes_ofb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx cx[1])
+
+    aes_ctr_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+            int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1])
+
+    aes_ctr_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+            int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1])
+
+can process blocks of any length.  Note also that CFB, OFB and CTR mode calls only
+use AES encryption contexts even during decryption operations.
+
+The calls CTR mode operations use a buffer (cbuf) which holds the counter value
+together with a function parameter:
+
+    void cbuf_inc(unsigned char *cbuf);
+
+that is ued to update the counter value after each 16 byte AES operation. The 
+counter buffer is updated appropriately to allow for incremental operations.
+
+Please note the following IMPORTANT points about the AES mode subroutines:
+
+    1. All modes are reset when a new AES key is set.
+    
+    2. Incremental calls to the different modes cannot 
+       be mixed. If a change of mode is needed a new 
+       key must be set or a reset must be issued (see 
+       below).
+       
+    3. For modes with IVs, the IV value is an inpu AND
+       an ouput since it is updated after each call to 
+       the value needed for any subsequent incremental
+       call(s). If the mode is reset, the IV hence has
+       to be set (or reset) as well.
+       
+    4. ECB operations must be multiples of 16 bytes
+       but do not need to be reset for new operations.
+       
+    5. CBC operations must also be multiples of 16 
+       bytes and are reset for a new operation by 
+       setting the IV.
+       
+    6. CFB, OFB and CTR mode must be reset by setting 
+       a new IV value AND by calling:
+       
+           aes_mode_reset(aes_encrypt_ctx cx[1])
+           
+       For CTR mode the cbuf value also has to be reset.
+       
+    7. CFB, OFB and CTR modes only use AES encryption 
+       operations and contexts and do not need AES
+       decrytpion operations.
+       
+    8. AES keys remain valid across resets and changes
+       of mode (but encryption and decryption keys must 
+       both be set if they are needed).  
+       
+   Brian Gladman  22/07/2008
+   
+ cbits/gladman/aes_modes.c view
@@ -0,0 +1,945 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+
+ These subroutines implement multiple block AES modes for ECB, CBC, CFB,
+ OFB and CTR encryption,  The code provides support for the VIA Advanced
+ Cryptography Engine (ACE).
+
+ NOTE: In the following subroutines, the AES contexts (ctx) must be
+ 16 byte aligned if VIA ACE is being used
+*/
+
+#include <string.h>
+#include <assert.h>
+
+#include "aesopt.h"
+
+#if defined( AES_MODES )
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+#if defined( _MSC_VER ) && ( _MSC_VER > 800 )
+#pragma intrinsic(memcpy)
+#endif
+
+#define BFR_BLOCKS      8
+
+/* These values are used to detect long word alignment in order to */
+/* speed up some buffer operations. This facility may not work on  */
+/* some machines so this define can be commented out if necessary  */
+
+#define FAST_BUFFER_OPERATIONS
+
+#define lp32(x)         ((uint_32t*)(x))
+
+#if defined( USE_VIA_ACE_IF_PRESENT )
+
+#include "aes_via_ace.h"
+
+#pragma pack(16)
+
+aligned_array(unsigned long,    enc_gen_table, 12, 16) =    NEH_ENC_GEN_DATA;
+aligned_array(unsigned long,   enc_load_table, 12, 16) =   NEH_ENC_LOAD_DATA;
+aligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA;
+aligned_array(unsigned long,    dec_gen_table, 12, 16) =    NEH_DEC_GEN_DATA;
+aligned_array(unsigned long,   dec_load_table, 12, 16) =   NEH_DEC_LOAD_DATA;
+aligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA;
+
+/* NOTE: These control word macros must only be used after  */
+/* a key has been set up because they depend on key size    */
+
+#if NEH_KEY_TYPE == NEH_LOAD
+#define kd_adr(c)   ((uint_8t*)(c)->ks)
+#elif NEH_KEY_TYPE == NEH_GENERATE
+#define kd_adr(c)   ((uint_8t*)(c)->ks + (c)->inf.b[0])
+#else
+#define kd_adr(c)   ((uint_8t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0))
+#endif
+
+#else
+
+#define aligned_array(type, name, no, stride) type name[no]
+#define aligned_auto(type, name, no, stride)  type name[no]
+
+#endif
+
+#if defined( _MSC_VER ) && _MSC_VER > 1200
+
+#define via_cwd(cwd, ty, dir, len) \
+    unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4))
+
+#else
+
+#define via_cwd(cwd, ty, dir, len)              \
+    aligned_auto(unsigned long, cwd, 4, 16);    \
+    cwd[1] = cwd[2] = cwd[3] = 0;               \
+    cwd[0] = neh_##dir##_##ty##_key(len)
+
+#endif
+
+/* test the code for detecting and setting pointer alignment */
+
+AES_RETURN aes_test_alignment_detection(unsigned int n)	/* 4 <= n <= 16 */
+{	uint_8t	p[16];
+	uint_32t i, count_eq = 0, count_neq = 0;
+
+	if(n < 4 || n > 16)
+		return EXIT_FAILURE;
+
+	for(i = 0; i < n; ++i)
+	{
+		uint_8t *qf = ALIGN_FLOOR(p + i, n),
+				*qh =  ALIGN_CEIL(p + i, n);
+		
+		if(qh == qf)
+			++count_eq;
+		else if(qh == qf + n)
+			++count_neq;
+		else
+			return EXIT_FAILURE;
+	}
+	return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+AES_RETURN aes_mode_reset(aes_encrypt_ctx ctx[1])
+{
+    ctx->inf.b[2] = 0;
+    return EXIT_SUCCESS;
+}
+
+AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, const aes_encrypt_ctx ctx[1])
+{   int nb = len >> 4;
+
+    if(len & (AES_BLOCK_SIZE - 1))
+        return EXIT_FAILURE;
+
+#if defined( USE_VIA_ACE_IF_PRESENT )
+
+    if(ctx->inf.b[1] == 0xff)
+    {   uint_8t *ksp = (uint_8t*)(ctx->ks);
+        via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
+
+        if(ALIGN_OFFSET( ctx, 16 ))
+            return EXIT_FAILURE;
+
+        if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
+        {
+            via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
+        }
+        else
+        {   aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
+            uint_8t *ip, *op;
+
+            while(nb)
+            {
+                int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
+
+                ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
+                op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
+
+                if(ip != ibuf)
+                    memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
+
+                via_ecb_op5(ksp, cwd, ip, op, m);
+
+                if(op != obuf)
+                    memcpy(obuf, buf, m * AES_BLOCK_SIZE);
+
+                ibuf += m * AES_BLOCK_SIZE;
+                obuf += m * AES_BLOCK_SIZE;
+                nb -= m;
+            }
+        }
+
+        return EXIT_SUCCESS;
+    }
+
+#endif
+
+#if !defined( ASSUME_VIA_ACE_PRESENT )
+    while(nb--)
+    {
+        if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+        ibuf += AES_BLOCK_SIZE;
+        obuf += AES_BLOCK_SIZE;
+    }
+#endif
+    return EXIT_SUCCESS;
+}
+
+AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, const aes_decrypt_ctx ctx[1])
+{   int nb = len >> 4;
+
+    if(len & (AES_BLOCK_SIZE - 1))
+        return EXIT_FAILURE;
+
+#if defined( USE_VIA_ACE_IF_PRESENT )
+
+    if(ctx->inf.b[1] == 0xff)
+    {   uint_8t *ksp = kd_adr(ctx);
+        via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
+
+        if(ALIGN_OFFSET( ctx, 16 ))
+            return EXIT_FAILURE;
+
+        if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
+        {
+            via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
+        }
+        else
+        {   aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
+            uint_8t *ip, *op;
+
+            while(nb)
+            {
+                int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
+
+                ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
+                op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
+
+                if(ip != ibuf)
+                    memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
+
+                via_ecb_op5(ksp, cwd, ip, op, m);
+
+                if(op != obuf)
+                    memcpy(obuf, buf, m * AES_BLOCK_SIZE);
+
+                ibuf += m * AES_BLOCK_SIZE;
+                obuf += m * AES_BLOCK_SIZE;
+                nb -= m;
+            }
+        }
+
+        return EXIT_SUCCESS;
+    }
+
+#endif
+
+#if !defined( ASSUME_VIA_ACE_PRESENT )
+    while(nb--)
+    {
+        if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+        ibuf += AES_BLOCK_SIZE;
+        obuf += AES_BLOCK_SIZE;
+    }
+#endif
+    return EXIT_SUCCESS;
+}
+
+AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, const aes_encrypt_ctx ctx[1])
+{   int nb = len >> 4;
+
+    if(len & (AES_BLOCK_SIZE - 1))
+        return EXIT_FAILURE;
+
+#if defined( USE_VIA_ACE_IF_PRESENT )
+
+    if(ctx->inf.b[1] == 0xff)
+    {   uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
+        aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
+        via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
+
+        if(ALIGN_OFFSET( ctx, 16 ))
+            return EXIT_FAILURE;
+
+        if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */
+        {
+            ivp = liv;
+            memcpy(liv, iv, AES_BLOCK_SIZE);
+        }
+
+        if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))
+        {
+            via_cbc_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
+        }
+        else
+        {   aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
+            uint_8t *ip, *op;
+
+            while(nb)
+            {
+                int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
+
+                ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
+                op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
+
+                if(ip != ibuf)
+                    memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
+
+                via_cbc_op7(ksp, cwd, ip, op, m, ivp, ivp);
+
+                if(op != obuf)
+                    memcpy(obuf, buf, m * AES_BLOCK_SIZE);
+
+                ibuf += m * AES_BLOCK_SIZE;
+                obuf += m * AES_BLOCK_SIZE;
+                nb -= m;
+            }
+        }
+
+        if(iv != ivp)
+            memcpy(iv, ivp, AES_BLOCK_SIZE);
+
+        return EXIT_SUCCESS;
+    }
+
+#endif
+
+#if !defined( ASSUME_VIA_ACE_PRESENT )
+# ifdef FAST_BUFFER_OPERATIONS
+    if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
+        while(nb--)
+        {
+            lp32(iv)[0] ^= lp32(ibuf)[0];
+            lp32(iv)[1] ^= lp32(ibuf)[1];
+            lp32(iv)[2] ^= lp32(ibuf)[2];
+            lp32(iv)[3] ^= lp32(ibuf)[3];
+            if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+				return EXIT_FAILURE;
+            memcpy(obuf, iv, AES_BLOCK_SIZE);
+            ibuf += AES_BLOCK_SIZE;
+            obuf += AES_BLOCK_SIZE;
+        }
+    else
+# endif
+        while(nb--)
+        {
+            iv[ 0] ^= ibuf[ 0]; iv[ 1] ^= ibuf[ 1];
+            iv[ 2] ^= ibuf[ 2]; iv[ 3] ^= ibuf[ 3];
+            iv[ 4] ^= ibuf[ 4]; iv[ 5] ^= ibuf[ 5];
+            iv[ 6] ^= ibuf[ 6]; iv[ 7] ^= ibuf[ 7];
+            iv[ 8] ^= ibuf[ 8]; iv[ 9] ^= ibuf[ 9];
+            iv[10] ^= ibuf[10]; iv[11] ^= ibuf[11];
+            iv[12] ^= ibuf[12]; iv[13] ^= ibuf[13];
+            iv[14] ^= ibuf[14]; iv[15] ^= ibuf[15];
+            if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+				return EXIT_FAILURE;
+            memcpy(obuf, iv, AES_BLOCK_SIZE);
+            ibuf += AES_BLOCK_SIZE;
+            obuf += AES_BLOCK_SIZE;
+        }
+#endif
+    return EXIT_SUCCESS;
+}
+
+AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, const aes_decrypt_ctx ctx[1])
+{   unsigned char tmp[AES_BLOCK_SIZE];
+    int nb = len >> 4;
+
+    if(len & (AES_BLOCK_SIZE - 1))
+        return EXIT_FAILURE;
+
+#if defined( USE_VIA_ACE_IF_PRESENT )
+
+    if(ctx->inf.b[1] == 0xff)
+    {   uint_8t *ksp = kd_adr(ctx), *ivp = iv;
+        aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
+        via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
+
+        if(ALIGN_OFFSET( ctx, 16 ))
+            return EXIT_FAILURE;
+
+        if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */
+        {
+            ivp = liv;
+            memcpy(liv, iv, AES_BLOCK_SIZE);
+        }
+
+        if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))
+        {
+            via_cbc_op6(ksp, cwd, ibuf, obuf, nb, ivp);
+        }
+        else
+        {   aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
+            uint_8t *ip, *op;
+
+            while(nb)
+            {
+                int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
+
+                ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
+                op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
+
+                if(ip != ibuf)
+                    memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
+
+                via_cbc_op6(ksp, cwd, ip, op, m, ivp);
+
+                if(op != obuf)
+                    memcpy(obuf, buf, m * AES_BLOCK_SIZE);
+
+                ibuf += m * AES_BLOCK_SIZE;
+                obuf += m * AES_BLOCK_SIZE;
+                nb -= m;
+            }
+        }
+
+        if(iv != ivp)
+            memcpy(iv, ivp, AES_BLOCK_SIZE);
+
+        return EXIT_SUCCESS;
+    }
+#endif
+
+#if !defined( ASSUME_VIA_ACE_PRESENT )
+# ifdef FAST_BUFFER_OPERATIONS
+    if(!ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
+        while(nb--)
+        {
+            memcpy(tmp, ibuf, AES_BLOCK_SIZE);
+            if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
+				return EXIT_FAILURE;
+            lp32(obuf)[0] ^= lp32(iv)[0];
+            lp32(obuf)[1] ^= lp32(iv)[1];
+            lp32(obuf)[2] ^= lp32(iv)[2];
+            lp32(obuf)[3] ^= lp32(iv)[3];
+            memcpy(iv, tmp, AES_BLOCK_SIZE);
+            ibuf += AES_BLOCK_SIZE;
+            obuf += AES_BLOCK_SIZE;
+        }
+    else
+# endif
+        while(nb--)
+        {
+            memcpy(tmp, ibuf, AES_BLOCK_SIZE);
+            if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
+				return EXIT_FAILURE;
+            obuf[ 0] ^= iv[ 0]; obuf[ 1] ^= iv[ 1];
+            obuf[ 2] ^= iv[ 2]; obuf[ 3] ^= iv[ 3];
+            obuf[ 4] ^= iv[ 4]; obuf[ 5] ^= iv[ 5];
+            obuf[ 6] ^= iv[ 6]; obuf[ 7] ^= iv[ 7];
+            obuf[ 8] ^= iv[ 8]; obuf[ 9] ^= iv[ 9];
+            obuf[10] ^= iv[10]; obuf[11] ^= iv[11];
+            obuf[12] ^= iv[12]; obuf[13] ^= iv[13];
+            obuf[14] ^= iv[14]; obuf[15] ^= iv[15];
+            memcpy(iv, tmp, AES_BLOCK_SIZE);
+            ibuf += AES_BLOCK_SIZE;
+            obuf += AES_BLOCK_SIZE;
+        }
+#endif
+    return EXIT_SUCCESS;
+}
+
+AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
+{   int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
+
+    if(b_pos)           /* complete any partial block   */
+    {
+        while(b_pos < AES_BLOCK_SIZE && cnt < len)
+        {
+            *obuf++ = (iv[b_pos++] ^= *ibuf++);
+            cnt++;
+        }
+
+        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
+    }
+
+    if((nb = (len - cnt) >> 4) != 0)    /* process whole blocks */
+    {
+#if defined( USE_VIA_ACE_IF_PRESENT )
+
+        if(ctx->inf.b[1] == 0xff)
+        {   int m;
+            uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
+            aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
+            via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
+
+            if(ALIGN_OFFSET( ctx, 16 ))
+                return EXIT_FAILURE;
+
+            if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */
+            {
+                ivp = liv;
+                memcpy(liv, iv, AES_BLOCK_SIZE);
+            }
+
+            if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
+            {
+                via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
+                ibuf += nb * AES_BLOCK_SIZE;
+                obuf += nb * AES_BLOCK_SIZE;
+                cnt  += nb * AES_BLOCK_SIZE;
+            }
+            else    /* input, output or both are unaligned  */
+            {   aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
+                uint_8t *ip, *op;
+
+                while(nb)
+                {
+                    m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
+
+                    ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
+                    op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
+
+                    if(ip != ibuf)
+                        memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
+
+                    via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp);
+
+                    if(op != obuf)
+                        memcpy(obuf, buf, m * AES_BLOCK_SIZE);
+
+                    ibuf += m * AES_BLOCK_SIZE;
+                    obuf += m * AES_BLOCK_SIZE;
+                    cnt  += m * AES_BLOCK_SIZE;
+                }
+            }
+
+            if(ivp != iv)
+                memcpy(iv, ivp, AES_BLOCK_SIZE);
+        }
+#else
+# ifdef FAST_BUFFER_OPERATIONS
+        if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
+            while(cnt + AES_BLOCK_SIZE <= len)
+            {
+                assert(b_pos == 0);
+                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+					return EXIT_FAILURE;
+                lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0];
+                lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1];
+                lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2];
+                lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3];
+                ibuf += AES_BLOCK_SIZE;
+                obuf += AES_BLOCK_SIZE;
+                cnt  += AES_BLOCK_SIZE;
+            }
+        else
+# endif
+            while(cnt + AES_BLOCK_SIZE <= len)
+            {
+                assert(b_pos == 0);
+                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+					return EXIT_FAILURE;
+                obuf[ 0] = iv[ 0] ^= ibuf[ 0]; obuf[ 1] = iv[ 1] ^= ibuf[ 1];
+                obuf[ 2] = iv[ 2] ^= ibuf[ 2]; obuf[ 3] = iv[ 3] ^= ibuf[ 3];
+                obuf[ 4] = iv[ 4] ^= ibuf[ 4]; obuf[ 5] = iv[ 5] ^= ibuf[ 5];
+                obuf[ 6] = iv[ 6] ^= ibuf[ 6]; obuf[ 7] = iv[ 7] ^= ibuf[ 7];
+                obuf[ 8] = iv[ 8] ^= ibuf[ 8]; obuf[ 9] = iv[ 9] ^= ibuf[ 9];
+                obuf[10] = iv[10] ^= ibuf[10]; obuf[11] = iv[11] ^= ibuf[11];
+                obuf[12] = iv[12] ^= ibuf[12]; obuf[13] = iv[13] ^= ibuf[13];
+                obuf[14] = iv[14] ^= ibuf[14]; obuf[15] = iv[15] ^= ibuf[15];
+                ibuf += AES_BLOCK_SIZE;
+                obuf += AES_BLOCK_SIZE;
+                cnt  += AES_BLOCK_SIZE;
+            }
+#endif
+    }
+
+    while(cnt < len)
+    {
+        if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+
+        while(cnt < len && b_pos < AES_BLOCK_SIZE)
+        {
+            *obuf++ = (iv[b_pos++] ^= *ibuf++);
+            cnt++;
+        }
+
+        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
+    }
+
+    ctx->inf.b[2] = (uint_8t)b_pos;
+    return EXIT_SUCCESS;
+}
+
+AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
+{   int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
+
+    if(b_pos)           /* complete any partial block   */
+    {   uint_8t t;
+
+        while(b_pos < AES_BLOCK_SIZE && cnt < len)
+        {
+            t = *ibuf++;
+            *obuf++ = t ^ iv[b_pos];
+            iv[b_pos++] = t;
+            cnt++;
+        }
+
+        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
+    }
+
+    if((nb = (len - cnt) >> 4) != 0)    /* process whole blocks */
+    {
+#if defined( USE_VIA_ACE_IF_PRESENT )
+
+        if(ctx->inf.b[1] == 0xff)
+        {   int m;
+            uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
+            aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
+            via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
+
+            if(ALIGN_OFFSET( ctx, 16 ))
+                return EXIT_FAILURE;
+
+            if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */
+            {
+                ivp = liv;
+                memcpy(liv, iv, AES_BLOCK_SIZE);
+            }
+
+            if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
+            {
+                via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
+                ibuf += nb * AES_BLOCK_SIZE;
+                obuf += nb * AES_BLOCK_SIZE;
+                cnt  += nb * AES_BLOCK_SIZE;
+            }
+            else    /* input, output or both are unaligned  */
+            {   aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
+                uint_8t *ip, *op;
+
+                while(nb)
+                {
+                    m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
+
+                    ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
+                    op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
+
+                    if(ip != ibuf)  /* input buffer is not aligned */
+                        memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
+
+                    via_cfb_op6(ksp, cwd, ip, op, m, ivp);
+
+                    if(op != obuf)  /* output buffer is not aligned */
+                        memcpy(obuf, buf, m * AES_BLOCK_SIZE);
+
+                    ibuf += m * AES_BLOCK_SIZE;
+                    obuf += m * AES_BLOCK_SIZE;
+                    cnt  += m * AES_BLOCK_SIZE;
+                }
+            }
+
+            if(ivp != iv)
+                memcpy(iv, ivp, AES_BLOCK_SIZE);
+        }
+#else
+# ifdef FAST_BUFFER_OPERATIONS
+        if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) &&!ALIGN_OFFSET( iv, 4 ))
+            while(cnt + AES_BLOCK_SIZE <= len)
+            {   uint_32t t;
+
+                assert(b_pos == 0);
+                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+					return EXIT_FAILURE;
+                t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t;
+                t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t;
+                t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t;
+                t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t;
+                ibuf += AES_BLOCK_SIZE;
+                obuf += AES_BLOCK_SIZE;
+                cnt  += AES_BLOCK_SIZE;
+            }
+        else
+# endif
+            while(cnt + AES_BLOCK_SIZE <= len)
+            {   uint_8t t;
+
+                assert(b_pos == 0);
+                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+					return EXIT_FAILURE;
+                t = ibuf[ 0], obuf[ 0] = t ^ iv[ 0], iv[ 0] = t;
+                t = ibuf[ 1], obuf[ 1] = t ^ iv[ 1], iv[ 1] = t;
+                t = ibuf[ 2], obuf[ 2] = t ^ iv[ 2], iv[ 2] = t;
+                t = ibuf[ 3], obuf[ 3] = t ^ iv[ 3], iv[ 3] = t;
+                t = ibuf[ 4], obuf[ 4] = t ^ iv[ 4], iv[ 4] = t;
+                t = ibuf[ 5], obuf[ 5] = t ^ iv[ 5], iv[ 5] = t;
+                t = ibuf[ 6], obuf[ 6] = t ^ iv[ 6], iv[ 6] = t;
+                t = ibuf[ 7], obuf[ 7] = t ^ iv[ 7], iv[ 7] = t;
+                t = ibuf[ 8], obuf[ 8] = t ^ iv[ 8], iv[ 8] = t;
+                t = ibuf[ 9], obuf[ 9] = t ^ iv[ 9], iv[ 9] = t;
+                t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t;
+                t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t;
+                t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t;
+                t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t;
+                t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t;
+                t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t;
+                ibuf += AES_BLOCK_SIZE;
+                obuf += AES_BLOCK_SIZE;
+                cnt  += AES_BLOCK_SIZE;
+            }
+#endif
+    }
+
+    while(cnt < len)
+    {   uint_8t t;
+
+        if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+
+        while(cnt < len && b_pos < AES_BLOCK_SIZE)
+        {
+            t = *ibuf++;
+            *obuf++ = t ^ iv[b_pos];
+            iv[b_pos++] = t;
+            cnt++;
+        }
+
+        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
+    }
+
+    ctx->inf.b[2] = (uint_8t)b_pos;
+    return EXIT_SUCCESS;
+}
+
+AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,
+                    int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
+{   int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
+
+    if(b_pos)           /* complete any partial block   */
+    {
+        while(b_pos < AES_BLOCK_SIZE && cnt < len)
+        {
+            *obuf++ = iv[b_pos++] ^ *ibuf++;
+            cnt++;
+        }
+
+        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
+    }
+
+    if((nb = (len - cnt) >> 4) != 0)   /* process whole blocks */
+    {
+#if defined( USE_VIA_ACE_IF_PRESENT )
+
+        if(ctx->inf.b[1] == 0xff)
+        {   int m;
+            uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
+            aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
+            via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
+
+            if(ALIGN_OFFSET( ctx, 16 ))
+                return EXIT_FAILURE;
+
+            if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */
+            {
+                ivp = liv;
+                memcpy(liv, iv, AES_BLOCK_SIZE);
+            }
+
+            if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
+            {
+                via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
+                ibuf += nb * AES_BLOCK_SIZE;
+                obuf += nb * AES_BLOCK_SIZE;
+                cnt  += nb * AES_BLOCK_SIZE;
+            }
+            else    /* input, output or both are unaligned  */
+        {   aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
+            uint_8t *ip, *op;
+
+                while(nb)
+                {
+                    m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
+
+                    ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
+                    op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
+
+                    if(ip != ibuf)
+                        memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
+
+                    via_ofb_op6(ksp, cwd, ip, op, m, ivp);
+
+                    if(op != obuf)
+                        memcpy(obuf, buf, m * AES_BLOCK_SIZE);
+
+                    ibuf += m * AES_BLOCK_SIZE;
+                    obuf += m * AES_BLOCK_SIZE;
+                    cnt  += m * AES_BLOCK_SIZE;
+                }
+            }
+
+            if(ivp != iv)
+                memcpy(iv, ivp, AES_BLOCK_SIZE);
+        }
+#else
+# ifdef FAST_BUFFER_OPERATIONS
+        if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
+            while(cnt + AES_BLOCK_SIZE <= len)
+            {
+                assert(b_pos == 0);
+                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+					return EXIT_FAILURE;
+                lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0];
+                lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1];
+                lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2];
+                lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3];
+                ibuf += AES_BLOCK_SIZE;
+                obuf += AES_BLOCK_SIZE;
+                cnt  += AES_BLOCK_SIZE;
+            }
+        else
+# endif
+            while(cnt + AES_BLOCK_SIZE <= len)
+            {
+                assert(b_pos == 0);
+                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+					return EXIT_FAILURE;
+                obuf[ 0] = iv[ 0] ^ ibuf[ 0]; obuf[ 1] = iv[ 1] ^ ibuf[ 1];
+                obuf[ 2] = iv[ 2] ^ ibuf[ 2]; obuf[ 3] = iv[ 3] ^ ibuf[ 3];
+                obuf[ 4] = iv[ 4] ^ ibuf[ 4]; obuf[ 5] = iv[ 5] ^ ibuf[ 5];
+                obuf[ 6] = iv[ 6] ^ ibuf[ 6]; obuf[ 7] = iv[ 7] ^ ibuf[ 7];
+                obuf[ 8] = iv[ 8] ^ ibuf[ 8]; obuf[ 9] = iv[ 9] ^ ibuf[ 9];
+                obuf[10] = iv[10] ^ ibuf[10]; obuf[11] = iv[11] ^ ibuf[11];
+                obuf[12] = iv[12] ^ ibuf[12]; obuf[13] = iv[13] ^ ibuf[13];
+                obuf[14] = iv[14] ^ ibuf[14]; obuf[15] = iv[15] ^ ibuf[15];
+                ibuf += AES_BLOCK_SIZE;
+                obuf += AES_BLOCK_SIZE;
+                cnt  += AES_BLOCK_SIZE;
+            }
+#endif
+    }
+
+    while(cnt < len)
+    {
+        if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+
+        while(cnt < len && b_pos < AES_BLOCK_SIZE)
+        {
+            *obuf++ = iv[b_pos++] ^ *ibuf++;
+            cnt++;
+        }
+
+        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
+    }
+
+    ctx->inf.b[2] = (uint_8t)b_pos;
+    return EXIT_SUCCESS;
+}
+
+#define BFR_LENGTH  (BFR_BLOCKS * AES_BLOCK_SIZE)
+
+AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,
+            int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx ctx[1])
+{   unsigned char   *ip;
+    int             i, blen, b_pos = (int)(ctx->inf.b[2]);
+
+#if defined( USE_VIA_ACE_IF_PRESENT )
+    aligned_auto(uint_8t, buf, BFR_LENGTH, 16);
+    if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET( ctx, 16 ))
+        return EXIT_FAILURE;
+#else
+    uint_8t buf[BFR_LENGTH];
+#endif
+
+    if(b_pos)
+    {
+        memcpy(buf, cbuf, AES_BLOCK_SIZE);
+        if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+
+        while(b_pos < AES_BLOCK_SIZE && len)
+        {
+            *obuf++ = *ibuf++ ^ buf[b_pos++];
+            --len;
+        }
+
+        if(len)
+            ctr_inc(cbuf), b_pos = 0;
+    }
+
+    while(len)
+    {
+        blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen;
+
+        for(i = 0, ip = buf; i < (blen >> 4); ++i)
+        {
+            memcpy(ip, cbuf, AES_BLOCK_SIZE);
+            ctr_inc(cbuf);
+            ip += AES_BLOCK_SIZE;
+        }
+
+        if(blen & (AES_BLOCK_SIZE - 1))
+            memcpy(ip, cbuf, AES_BLOCK_SIZE), i++;
+
+#if defined( USE_VIA_ACE_IF_PRESENT )
+        if(ctx->inf.b[1] == 0xff)
+        {
+            via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
+            via_ecb_op5((ctx->ks), cwd, buf, buf, i);
+        }
+        else
+#endif
+        if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+
+        i = 0; ip = buf;
+# ifdef FAST_BUFFER_OPERATIONS
+        if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( ip, 4 ))
+            while(i + AES_BLOCK_SIZE <= blen)
+            {
+                lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0];
+                lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1];
+                lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2];
+                lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3];
+                i += AES_BLOCK_SIZE;
+                ip += AES_BLOCK_SIZE;
+                ibuf += AES_BLOCK_SIZE;
+                obuf += AES_BLOCK_SIZE;
+            }
+        else
+#endif
+            while(i + AES_BLOCK_SIZE <= blen)
+            {
+                obuf[ 0] = ibuf[ 0] ^ ip[ 0]; obuf[ 1] = ibuf[ 1] ^ ip[ 1];
+                obuf[ 2] = ibuf[ 2] ^ ip[ 2]; obuf[ 3] = ibuf[ 3] ^ ip[ 3];
+                obuf[ 4] = ibuf[ 4] ^ ip[ 4]; obuf[ 5] = ibuf[ 5] ^ ip[ 5];
+                obuf[ 6] = ibuf[ 6] ^ ip[ 6]; obuf[ 7] = ibuf[ 7] ^ ip[ 7];
+                obuf[ 8] = ibuf[ 8] ^ ip[ 8]; obuf[ 9] = ibuf[ 9] ^ ip[ 9];
+                obuf[10] = ibuf[10] ^ ip[10]; obuf[11] = ibuf[11] ^ ip[11];
+                obuf[12] = ibuf[12] ^ ip[12]; obuf[13] = ibuf[13] ^ ip[13];
+                obuf[14] = ibuf[14] ^ ip[14]; obuf[15] = ibuf[15] ^ ip[15];
+                i += AES_BLOCK_SIZE;
+                ip += AES_BLOCK_SIZE;
+                ibuf += AES_BLOCK_SIZE;
+                obuf += AES_BLOCK_SIZE;
+            }
+
+        while(i++ < blen)
+            *obuf++ = *ibuf++ ^ ip[b_pos++];
+    }
+
+    ctx->inf.b[2] = (uint_8t)b_pos;
+    return EXIT_SUCCESS;
+}
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
+ cbits/gladman/aes_via_ace.h view
@@ -0,0 +1,529 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/20077
+*/
+
+#ifndef AES_VIA_ACE_H
+#define AES_VIA_ACE_H
+
+#if defined( _MSC_VER )
+#  define INLINE  __inline
+#elif defined( __GNUC__ )
+#  define INLINE  static inline
+#else
+#  error VIA ACE requires Microsoft or GNU C
+#endif
+
+#define NEH_GENERATE    1
+#define NEH_LOAD        2
+#define NEH_HYBRID      3
+
+#define MAX_READ_ATTEMPTS   1000
+
+/* VIA Nehemiah RNG and ACE Feature Mask Values */
+
+#define NEH_CPU_IS_VIA      0x00000001
+#define NEH_CPU_READ        0x00000010
+#define NEH_CPU_MASK        0x00000011
+
+#define NEH_RNG_PRESENT     0x00000004
+#define NEH_RNG_ENABLED     0x00000008
+#define NEH_ACE_PRESENT     0x00000040
+#define NEH_ACE_ENABLED     0x00000080
+#define NEH_RNG_FLAGS       (NEH_RNG_PRESENT | NEH_RNG_ENABLED)
+#define NEH_ACE_FLAGS       (NEH_ACE_PRESENT | NEH_ACE_ENABLED)
+#define NEH_FLAGS_MASK      (NEH_RNG_FLAGS | NEH_ACE_FLAGS)
+
+/* VIA Nehemiah Advanced Cryptography Engine (ACE) Control Word Values  */
+
+#define NEH_GEN_KEY     0x00000000      /* generate key schedule        */
+#define NEH_LOAD_KEY    0x00000080      /* load schedule from memory    */
+#define NEH_ENCRYPT     0x00000000      /* encryption                   */
+#define NEH_DECRYPT     0x00000200      /* decryption                   */
+#define NEH_KEY128      0x00000000+0x0a /* 128 bit key                  */
+#define NEH_KEY192      0x00000400+0x0c /* 192 bit key                  */
+#define NEH_KEY256      0x00000800+0x0e /* 256 bit key                  */
+
+#define NEH_ENC_GEN     (NEH_ENCRYPT | NEH_GEN_KEY)
+#define NEH_DEC_GEN     (NEH_DECRYPT | NEH_GEN_KEY)
+#define NEH_ENC_LOAD    (NEH_ENCRYPT | NEH_LOAD_KEY)
+#define NEH_DEC_LOAD    (NEH_DECRYPT | NEH_LOAD_KEY)
+
+#define NEH_ENC_GEN_DATA {\
+    NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\
+    NEH_ENC_GEN | NEH_KEY192, 0, 0, 0,\
+    NEH_ENC_GEN | NEH_KEY256, 0, 0, 0 }
+
+#define NEH_ENC_LOAD_DATA {\
+    NEH_ENC_LOAD | NEH_KEY128, 0, 0, 0,\
+    NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\
+    NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 }
+
+#define NEH_ENC_HYBRID_DATA {\
+    NEH_ENC_GEN  | NEH_KEY128, 0, 0, 0,\
+    NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\
+    NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 }
+
+#define NEH_DEC_GEN_DATA {\
+    NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\
+    NEH_DEC_GEN | NEH_KEY192, 0, 0, 0,\
+    NEH_DEC_GEN | NEH_KEY256, 0, 0, 0 }
+
+#define NEH_DEC_LOAD_DATA {\
+    NEH_DEC_LOAD | NEH_KEY128, 0, 0, 0,\
+    NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\
+    NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 }
+
+#define NEH_DEC_HYBRID_DATA {\
+    NEH_DEC_GEN  | NEH_KEY128, 0, 0, 0,\
+    NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\
+    NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 }
+
+#define neh_enc_gen_key(x)  ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) :      \
+     (x) == 192 ? (NEH_ENC_GEN | NEH_KEY192) : (NEH_ENC_GEN | NEH_KEY256))
+
+#define neh_enc_load_key(x) ((x) == 128 ? (NEH_ENC_LOAD | NEH_KEY128) :     \
+     (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256))
+
+#define neh_enc_hybrid_key(x)   ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) :  \
+     (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256))
+
+#define neh_dec_gen_key(x)  ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) :      \
+     (x) == 192 ? (NEH_DEC_GEN | NEH_KEY192) : (NEH_DEC_GEN | NEH_KEY256))
+
+#define neh_dec_load_key(x) ((x) == 128 ? (NEH_DEC_LOAD | NEH_KEY128) :     \
+     (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256))
+
+#define neh_dec_hybrid_key(x)   ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) :  \
+     (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256))
+
+#if defined( _MSC_VER ) && ( _MSC_VER > 1200 )
+#define aligned_auto(type, name, no, stride)  __declspec(align(stride)) type name[no]
+#else
+#define aligned_auto(type, name, no, stride)                \
+    unsigned char _##name[no * sizeof(type) + stride];      \
+    type *name = (type*)(16 * ((((unsigned long)(_##name)) + stride - 1) / stride))
+#endif
+
+#if defined( _MSC_VER ) && ( _MSC_VER > 1200 )
+#define aligned_array(type, name, no, stride) __declspec(align(stride)) type name[no]
+#elif defined( __GNUC__ )
+#define aligned_array(type, name, no, stride) type name[no] __attribute__ ((aligned(stride)))
+#else
+#define aligned_array(type, name, no, stride) type name[no]
+#endif
+
+/* VIA ACE codeword     */
+
+static unsigned char via_flags = 0;
+
+#if defined ( _MSC_VER ) && ( _MSC_VER > 800 )
+
+#define NEH_REKEY   __asm pushfd __asm popfd
+#define NEH_AES     __asm _emit 0xf3 __asm _emit 0x0f __asm _emit 0xa7
+#define NEH_ECB     NEH_AES __asm _emit 0xc8
+#define NEH_CBC     NEH_AES __asm _emit 0xd0
+#define NEH_CFB     NEH_AES __asm _emit 0xe0
+#define NEH_OFB     NEH_AES __asm _emit 0xe8
+#define NEH_RNG     __asm _emit 0x0f __asm _emit 0xa7 __asm _emit 0xc0
+
+INLINE int has_cpuid(void)
+{   char ret_value;
+    __asm
+    {   pushfd                  /* save EFLAGS register     */
+        mov     eax,[esp]       /* copy it to eax           */
+        mov     edx,0x00200000  /* CPUID bit position       */
+        xor     eax,edx         /* toggle the CPUID bit     */
+        push    eax             /* attempt to set EFLAGS to */
+        popfd                   /*     the new value        */
+        pushfd                  /* get the new EFLAGS value */
+        pop     eax             /*     into eax             */
+        xor     eax,[esp]       /* xor with original value  */
+        and     eax,edx         /* has CPUID bit changed?   */
+        setne   al              /* set to 1 if we have been */
+        mov     ret_value,al    /*     able to change it    */
+        popfd                   /* restore original EFLAGS  */
+    }
+    return (int)ret_value;
+}
+
+INLINE int is_via_cpu(void)
+{   char ret_value;
+    __asm
+    {   xor     eax,eax         /* use CPUID to get vendor  */
+        cpuid                   /* identity string          */
+        xor     eax,eax         /* is it "CentaurHauls" ?   */
+        sub     ebx,0x746e6543  /* 'Cent'                   */
+        or      eax,ebx
+        sub     edx,0x48727561  /* 'aurH'                   */
+        or      eax,edx
+        sub     ecx,0x736c7561  /* 'auls'                   */
+        or      eax,ecx
+        sete    al              /* set to 1 if it is VIA ID */
+        mov     dl,NEH_CPU_READ /* mark CPU type as read    */
+        or      dl,al           /* & store result in flags  */
+        mov     [via_flags],dl  /* set VIA detected flag    */
+        mov     ret_value,al    /*     able to change it    */
+    }
+    return (int)ret_value;
+}
+
+INLINE int read_via_flags(void)
+{   char ret_value = 0;
+    __asm
+    {
+        mov     eax,0xC0000000  /* Centaur extended CPUID   */
+        cpuid
+        mov     edx,0xc0000001  /* >= 0xc0000001 if support */
+        cmp     eax,edx         /* for VIA extended feature */
+        jnae    no_rng          /*     flags is available   */
+        mov     eax,edx         /* read Centaur extended    */
+        cpuid                   /*     feature flags        */
+        mov     eax,NEH_FLAGS_MASK  /* mask out and save    */
+        and     eax,edx         /*  the RNG and ACE flags   */
+        or      [via_flags],al  /* present & enabled flags  */
+        mov     ret_value,al    /*     able to change it    */
+no_rng:
+    }
+    return (int)ret_value;
+}
+
+INLINE unsigned int via_rng_in(void *buf)
+{   char ret_value = 0x1f;
+    __asm
+    {
+        push    edi
+        mov     edi,buf         /* input buffer address     */
+        xor     edx,edx         /* try to fetch 8 bytes     */
+        NEH_RNG                 /* do RNG read operation    */
+        and     ret_value,al    /* count of bytes returned  */
+        pop     edi
+    }
+    return (int)ret_value;
+}
+
+INLINE void via_ecb_op5(
+            const void *k, const void *c, const void *s, void *d, int l)
+{   __asm
+    {
+        NEH_REKEY
+        mov     ebx, (k)
+        mov     edx, (c)
+        mov     esi, (s)
+        mov     edi, (d)
+        mov     ecx, (l)
+        NEH_ECB
+    }
+}
+
+INLINE void via_cbc_op6(
+            const void *k, const void *c, const void *s, void *d, int l, void *v)
+{   __asm
+    {
+        NEH_REKEY
+        mov     ebx, (k)
+        mov     edx, (c)
+        mov     esi, (s)
+        mov     edi, (d)
+        mov     ecx, (l)
+        mov     eax, (v)
+        NEH_CBC
+    }
+}
+
+INLINE void via_cbc_op7(
+        const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)
+{   __asm
+    {
+        NEH_REKEY
+        mov     ebx, (k)
+        mov     edx, (c)
+        mov     esi, (s)
+        mov     edi, (d)
+        mov     ecx, (l)
+        mov     eax, (v)
+        NEH_CBC
+        mov     esi, eax
+        mov     edi, (w)
+        movsd
+        movsd
+        movsd
+        movsd
+    }
+}
+
+INLINE void via_cfb_op6(
+            const void *k, const void *c, const void *s, void *d, int l, void *v)
+{   __asm
+    {
+        NEH_REKEY
+        mov     ebx, (k)
+        mov     edx, (c)
+        mov     esi, (s)
+        mov     edi, (d)
+        mov     ecx, (l)
+        mov     eax, (v)
+        NEH_CFB
+    }
+}
+
+INLINE void via_cfb_op7(
+        const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)
+{   __asm
+    {
+        NEH_REKEY
+        mov     ebx, (k)
+        mov     edx, (c)
+        mov     esi, (s)
+        mov     edi, (d)
+        mov     ecx, (l)
+        mov     eax, (v)
+        NEH_CFB
+        mov     esi, eax
+        mov     edi, (w)
+        movsd
+        movsd
+        movsd
+        movsd
+    }
+}
+
+INLINE void via_ofb_op6(
+            const void *k, const void *c, const void *s, void *d, int l, void *v)
+{   __asm
+    {
+        NEH_REKEY
+        mov     ebx, (k)
+        mov     edx, (c)
+        mov     esi, (s)
+        mov     edi, (d)
+        mov     ecx, (l)
+        mov     eax, (v)
+        NEH_OFB
+    }
+}
+
+#elif defined( __GNUC__ )
+
+#define NEH_REKEY   asm("pushfl\n popfl\n\t")
+#define NEH_ECB     asm(".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t")
+#define NEH_CBC     asm(".byte 0xf3, 0x0f, 0xa7, 0xd0\n\t")
+#define NEH_CFB     asm(".byte 0xf3, 0x0f, 0xa7, 0xe0\n\t")
+#define NEH_OFB     asm(".byte 0xf3, 0x0f, 0xa7, 0xe8\n\t")
+#define NEH_RNG     asm(".byte 0x0f, 0xa7, 0xc0\n\t");
+
+INLINE int has_cpuid(void)
+{   int val;
+    asm("pushfl\n\t");
+    asm("movl  0(%esp),%eax\n\t");
+    asm("xor   $0x00200000,%eax\n\t");
+    asm("pushl %eax\n\t");
+    asm("popfl\n\t");
+    asm("pushfl\n\t");
+    asm("popl  %eax\n\t");
+    asm("xorl  0(%esp),%edx\n\t");
+    asm("andl  $0x00200000,%eax\n\t");
+    asm("movl  %%eax,%0\n\t" : "=m" (val));
+    asm("popfl\n\t");
+    return val ? 1 : 0;
+}
+
+INLINE int is_via_cpu(void)
+{   int val;
+    asm("xorl %eax,%eax\n\t");
+    asm("cpuid\n\t");
+    asm("xorl %eax,%eax\n\t");
+    asm("subl $0x746e6543,%ebx\n\t");
+    asm("orl  %ebx,%eax\n\t");
+    asm("subl $0x48727561,%edx\n\t");
+    asm("orl  %edx,%eax\n\t");
+    asm("subl $0x736c7561,%ecx\n\t");
+    asm("orl  %ecx,%eax\n\t");
+    asm("movl %%eax,%0\n\t" : "=m" (val));
+    val = (val ? 0 : 1);
+    via_flags = (val | NEH_CPU_READ);
+    return val;
+}
+
+INLINE int read_via_flags(void)
+{   unsigned char   val;
+    asm("movl $0xc0000000,%eax\n\t");
+    asm("cpuid\n\t");
+    asm("movl $0xc0000001,%edx\n\t");
+    asm("cmpl %edx,%eax\n\t");
+    asm("setae %al\n\t");
+    asm("movb %%al,%0\n\t" : "=m" (val));
+    if(!val) return 0;
+    asm("movl $0xc0000001,%eax\n\t");
+    asm("cpuid\n\t");
+    asm("movb %%dl,%0\n\t" : "=m" (val));
+    val &= NEH_FLAGS_MASK;
+    via_flags |= val;
+    return (int) val;
+}
+
+INLINE int via_rng_in(void *buf)
+{   int val;
+    asm("pushl %edi\n\t");
+    asm("movl %0,%%edi\n\t" : : "m" (buf));
+    asm("xorl %edx,%edx\n\t");
+    NEH_RNG
+    asm("andl $0x0000001f,%eax\n\t");
+    asm("movl %%eax,%0\n\t" : "=m" (val));
+    asm("popl %edi\n\t");
+    return val;
+}
+
+INLINE volatile  void via_ecb_op5(
+            const void *k, const void *c, const void *s, void *d, int l)
+{
+    NEH_REKEY;
+    asm("movl %0, %%ebx\n\t" : : "m" (k));
+    asm("movl %0, %%edx\n\t" : : "m" (c));
+    asm("movl %0, %%esi\n\t" : : "m" (s));
+    asm("movl %0, %%edi\n\t" : : "m" (d));
+    asm("movl %0, %%ecx\n\t" : : "m" (l));
+    NEH_ECB;
+}
+
+INLINE volatile  void via_cbc_op6(
+            const void *k, const void *c, const void *s, void *d, int l, void *v)
+{
+    NEH_REKEY;
+    asm("movl %0, %%ebx\n\t" : : "m" (k));
+    asm("movl %0, %%edx\n\t" : : "m" (c));
+    asm("movl %0, %%esi\n\t" : : "m" (s));
+    asm("movl %0, %%edi\n\t" : : "m" (d));
+    asm("movl %0, %%ecx\n\t" : : "m" (l));
+    asm("movl %0, %%eax\n\t" : : "m" (v));
+    NEH_CBC;
+}
+
+INLINE volatile  void via_cbc_op7(
+        const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)
+{
+    NEH_REKEY;
+    asm("movl %0, %%ebx\n\t" : : "m" (k));
+    asm("movl %0, %%edx\n\t" : : "m" (c));
+    asm("movl %0, %%esi\n\t" : : "m" (s));
+    asm("movl %0, %%edi\n\t" : : "m" (d));
+    asm("movl %0, %%ecx\n\t" : : "m" (l));
+    asm("movl %0, %%eax\n\t" : : "m" (v));
+    NEH_CBC;
+    asm("movl %eax,%esi\n\t");
+    asm("movl %0, %%edi\n\t" : : "m" (w));
+    asm("movsl; movsl; movsl; movsl\n\t");
+}
+
+INLINE volatile  void via_cfb_op6(
+            const void *k, const void *c, const void *s, void *d, int l, void *v)
+{
+    NEH_REKEY;
+    asm("movl %0, %%ebx\n\t" : : "m" (k));
+    asm("movl %0, %%edx\n\t" : : "m" (c));
+    asm("movl %0, %%esi\n\t" : : "m" (s));
+    asm("movl %0, %%edi\n\t" : : "m" (d));
+    asm("movl %0, %%ecx\n\t" : : "m" (l));
+    asm("movl %0, %%eax\n\t" : : "m" (v));
+    NEH_CFB;
+}
+
+INLINE volatile  void via_cfb_op7(
+        const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)
+{
+    NEH_REKEY;
+    asm("movl %0, %%ebx\n\t" : : "m" (k));
+    asm("movl %0, %%edx\n\t" : : "m" (c));
+    asm("movl %0, %%esi\n\t" : : "m" (s));
+    asm("movl %0, %%edi\n\t" : : "m" (d));
+    asm("movl %0, %%ecx\n\t" : : "m" (l));
+    asm("movl %0, %%eax\n\t" : : "m" (v));
+    NEH_CFB;
+    asm("movl %eax,%esi\n\t");
+    asm("movl %0, %%edi\n\t" : : "m" (w));
+    asm("movsl; movsl; movsl; movsl\n\t");
+}
+
+INLINE volatile  void via_ofb_op6(
+            const void *k, const void *c, const void *s, void *d, int l, void *v)
+{
+    NEH_REKEY;
+    asm("movl %0, %%ebx\n\t" : : "m" (k));
+    asm("movl %0, %%edx\n\t" : : "m" (c));
+    asm("movl %0, %%esi\n\t" : : "m" (s));
+    asm("movl %0, %%edi\n\t" : : "m" (d));
+    asm("movl %0, %%ecx\n\t" : : "m" (l));
+    asm("movl %0, %%eax\n\t" : : "m" (v));
+    NEH_OFB;
+}
+
+#else
+#error VIA ACE is not available with this compiler
+#endif
+
+INLINE int via_ace_test(void)
+{
+    return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_ACE_FLAGS) == NEH_ACE_FLAGS);
+}
+
+#define VIA_ACE_AVAILABLE   (((via_flags & NEH_ACE_FLAGS) == NEH_ACE_FLAGS)         \
+    || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_ace_test())
+
+INLINE int via_rng_test(void)
+{
+    return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_RNG_FLAGS) == NEH_RNG_FLAGS);
+}
+
+#define VIA_RNG_AVAILABLE   (((via_flags & NEH_RNG_FLAGS) == NEH_RNG_FLAGS)         \
+    || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_rng_test())
+
+INLINE int read_via_rng(void *buf, int count)
+{   int nbr, max_reads, lcnt = count;
+    unsigned char *p, *q;
+    aligned_auto(unsigned char, bp, 64, 16);
+
+    if(!VIA_RNG_AVAILABLE)
+        return 0;
+
+    do
+    {
+        max_reads = MAX_READ_ATTEMPTS;
+        do
+            nbr = via_rng_in(bp);
+        while
+            (nbr == 0 && --max_reads);
+
+        lcnt -= nbr;
+        p = (unsigned char*)buf; q = bp;
+        while(nbr--)
+            *p++ = *q++;
+    }
+    while
+        (lcnt && max_reads);
+
+    return count - lcnt;
+}
+
+#endif
+ cbits/gladman/aescrypt.c view
@@ -0,0 +1,301 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+*/
+
+#include "aesopt.h"
+#include "aestab.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
+#define so(y,x,c)   word_out(y, c, s(x,c))
+
+#if defined(ARRAYS)
+#define locals(y,x)     x[4],y[4]
+#else
+#define locals(y,x)     x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
+#endif
+
+#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \
+                        s(y,2) = s(x,2); s(y,3) = s(x,3);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
+#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
+
+#if ( FUNCS_IN_C & ENCRYPTION_IN_C )
+
+/* Visual C++ .Net v7.1 provides the fastest encryption code when using
+   Pentium optimiation with small code but this is poor for decryption
+   so we need to control this with the following VC++ pragmas
+*/
+
+#if defined( _MSC_VER ) && !defined( _WIN64 )
+#pragma optimize( "s", on )
+#endif
+
+/* Given the column (c) of the output state variable, the following
+   macros give the input state variables which are needed in its
+   computation for each row (r) of the state. All the alternative
+   macros give the same end values but expand into different ways
+   of calculating these values.  In particular the complex macro
+   used for dynamically variable block sizes is designed to expand
+   to a compile time constant whenever possible but will expand to
+   conditional clauses on some branches (I am grateful to Frank
+   Yellin for this construction)
+*/
+
+#define fwd_var(x,r,c)\
+ ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
+ : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
+ : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
+ :          ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
+
+#if defined(FT4_SET)
+#undef  dec_fmvars
+#define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
+#elif defined(FT1_SET)
+#undef  dec_fmvars
+#define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))
+#else
+#define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)))
+#endif
+
+#if defined(FL4_SET)
+#define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
+#elif defined(FL1_SET)
+#define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))
+#else
+#define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))
+#endif
+
+AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1])
+{   uint_32t         locals(b0, b1);
+    const uint_32t   *kp;
+#if defined( dec_fmvars )
+    dec_fmvars; /* declare variables for fwd_mcol() if needed */
+#endif
+
+    if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 )
+        return EXIT_FAILURE;
+
+    kp = cx->ks;
+    state_in(b0, in, kp);
+
+#if (ENC_UNROLL == FULL)
+
+    switch(cx->inf.b[0])
+    {
+    case 14 * 16:
+        round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
+        round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
+        kp += 2 * N_COLS;
+    case 12 * 16:
+        round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
+        round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
+        kp += 2 * N_COLS;
+    case 10 * 16:
+        round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);
+        round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);
+        round(fwd_rnd,  b1, b0, kp + 3 * N_COLS);
+        round(fwd_rnd,  b0, b1, kp + 4 * N_COLS);
+        round(fwd_rnd,  b1, b0, kp + 5 * N_COLS);
+        round(fwd_rnd,  b0, b1, kp + 6 * N_COLS);
+        round(fwd_rnd,  b1, b0, kp + 7 * N_COLS);
+        round(fwd_rnd,  b0, b1, kp + 8 * N_COLS);
+        round(fwd_rnd,  b1, b0, kp + 9 * N_COLS);
+        round(fwd_lrnd, b0, b1, kp +10 * N_COLS);
+    }
+
+#else
+
+#if (ENC_UNROLL == PARTIAL)
+    {   uint_32t    rnd;
+        for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd)
+        {
+            kp += N_COLS;
+            round(fwd_rnd, b1, b0, kp);
+            kp += N_COLS;
+            round(fwd_rnd, b0, b1, kp);
+        }
+        kp += N_COLS;
+        round(fwd_rnd,  b1, b0, kp);
+#else
+    {   uint_32t    rnd;
+        for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd)
+        {
+            kp += N_COLS;
+            round(fwd_rnd, b1, b0, kp);
+            l_copy(b0, b1);
+        }
+#endif
+        kp += N_COLS;
+        round(fwd_lrnd, b0, b1, kp);
+    }
+#endif
+
+    state_out(out, b0);
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if ( FUNCS_IN_C & DECRYPTION_IN_C)
+
+/* Visual C++ .Net v7.1 provides the fastest encryption code when using
+   Pentium optimiation with small code but this is poor for decryption
+   so we need to control this with the following VC++ pragmas
+*/
+
+#if defined( _MSC_VER ) && !defined( _WIN64 )
+#pragma optimize( "t", on )
+#endif
+
+/* Given the column (c) of the output state variable, the following
+   macros give the input state variables which are needed in its
+   computation for each row (r) of the state. All the alternative
+   macros give the same end values but expand into different ways
+   of calculating these values.  In particular the complex macro
+   used for dynamically variable block sizes is designed to expand
+   to a compile time constant whenever possible but will expand to
+   conditional clauses on some branches (I am grateful to Frank
+   Yellin for this construction)
+*/
+
+#define inv_var(x,r,c)\
+ ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
+ : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
+ : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
+ :          ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
+
+#if defined(IT4_SET)
+#undef  dec_imvars
+#define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
+#elif defined(IT1_SET)
+#undef  dec_imvars
+#define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
+#else
+#define inv_rnd(y,x,k,c)    (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)))
+#endif
+
+#if defined(IL4_SET)
+#define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
+#elif defined(IL1_SET)
+#define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
+#else
+#define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
+#endif
+
+/* This code can work with the decryption key schedule in the   */
+/* order that is used for encrytpion (where the 1st decryption  */
+/* round key is at the high end ot the schedule) or with a key  */
+/* schedule that has been reversed to put the 1st decryption    */
+/* round key at the low end of the schedule in memory (when     */
+/* AES_REV_DKS is defined)                                      */
+
+#ifdef AES_REV_DKS
+#define key_ofs     0
+#define rnd_key(n)  (kp + n * N_COLS)
+#else
+#define key_ofs     1
+#define rnd_key(n)  (kp - n * N_COLS)
+#endif
+
+AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1])
+{   uint_32t        locals(b0, b1);
+#if defined( dec_imvars )
+    dec_imvars; /* declare variables for inv_mcol() if needed */
+#endif
+    const uint_32t *kp;
+
+    if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 )
+        return EXIT_FAILURE;
+
+    kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0);
+    state_in(b0, in, kp);
+
+#if (DEC_UNROLL == FULL)
+
+    kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2));
+    switch(cx->inf.b[0])
+    {
+    case 14 * 16:
+        round(inv_rnd,  b1, b0, rnd_key(-13));
+        round(inv_rnd,  b0, b1, rnd_key(-12));
+    case 12 * 16:
+        round(inv_rnd,  b1, b0, rnd_key(-11));
+        round(inv_rnd,  b0, b1, rnd_key(-10));
+    case 10 * 16:
+        round(inv_rnd,  b1, b0, rnd_key(-9));
+        round(inv_rnd,  b0, b1, rnd_key(-8));
+        round(inv_rnd,  b1, b0, rnd_key(-7));
+        round(inv_rnd,  b0, b1, rnd_key(-6));
+        round(inv_rnd,  b1, b0, rnd_key(-5));
+        round(inv_rnd,  b0, b1, rnd_key(-4));
+        round(inv_rnd,  b1, b0, rnd_key(-3));
+        round(inv_rnd,  b0, b1, rnd_key(-2));
+        round(inv_rnd,  b1, b0, rnd_key(-1));
+        round(inv_lrnd, b0, b1, rnd_key( 0));
+    }
+
+#else
+
+#if (DEC_UNROLL == PARTIAL)
+    {   uint_32t    rnd;
+        for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd)
+        {
+            kp = rnd_key(1);
+            round(inv_rnd, b1, b0, kp);
+            kp = rnd_key(1);
+            round(inv_rnd, b0, b1, kp);
+        }
+        kp = rnd_key(1);
+        round(inv_rnd, b1, b0, kp);
+#else
+    {   uint_32t    rnd;
+        for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd)
+        {
+            kp = rnd_key(1);
+            round(inv_rnd, b1, b0, kp);
+            l_copy(b0, b1);
+        }
+#endif
+        kp = rnd_key(1);
+        round(inv_lrnd, b0, b1, kp);
+        }
+#endif
+
+    state_out(out, b0);
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+ cbits/gladman/aeskey.c view
@@ -0,0 +1,555 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+*/
+
+#include "aesopt.h"
+#include "aestab.h"
+
+#ifdef USE_VIA_ACE_IF_PRESENT
+#  include "aes_via_ace.h"
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/* Initialise the key schedule from the user supplied key. The key
+   length can be specified in bytes, with legal values of 16, 24
+   and 32, or in bits, with legal values of 128, 192 and 256. These
+   values correspond with Nk values of 4, 6 and 8 respectively.
+
+   The following macros implement a single cycle in the key
+   schedule generation process. The number of cycles needed
+   for each cx->n_col and nk value is:
+
+    nk =             4  5  6  7  8
+    ------------------------------
+    cx->n_col = 4   10  9  8  7  7
+    cx->n_col = 5   14 11 10  9  9
+    cx->n_col = 6   19 15 12 11 11
+    cx->n_col = 7   21 19 16 13 14
+    cx->n_col = 8   29 23 19 17 14
+*/
+
+#if defined( REDUCE_CODE_SIZE )
+#  define ls_box ls_sub
+   uint_32t ls_sub(const uint_32t t, const uint_32t n);
+#  define inv_mcol im_sub
+   uint_32t im_sub(const uint_32t x);
+#  ifdef ENC_KS_UNROLL
+#    undef ENC_KS_UNROLL
+#  endif
+#  ifdef DEC_KS_UNROLL
+#    undef DEC_KS_UNROLL
+#  endif
+#endif
+
+#if (FUNCS_IN_C & ENC_KEYING_IN_C)
+
+#if defined(AES_128) || defined( AES_VAR )
+
+#define ke4(k,i) \
+{   k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \
+    k[4*(i)+5] = ss[1] ^= ss[0]; \
+    k[4*(i)+6] = ss[2] ^= ss[1]; \
+    k[4*(i)+7] = ss[3] ^= ss[2]; \
+}
+
+AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1])
+{   uint_32t    ss[4];
+
+    cx->ks[0] = ss[0] = word_in(key, 0);
+    cx->ks[1] = ss[1] = word_in(key, 1);
+    cx->ks[2] = ss[2] = word_in(key, 2);
+    cx->ks[3] = ss[3] = word_in(key, 3);
+
+#ifdef ENC_KS_UNROLL
+    ke4(cx->ks, 0);  ke4(cx->ks, 1);
+    ke4(cx->ks, 2);  ke4(cx->ks, 3);
+    ke4(cx->ks, 4);  ke4(cx->ks, 5);
+    ke4(cx->ks, 6);  ke4(cx->ks, 7);
+    ke4(cx->ks, 8);
+#else
+    {   uint_32t i;
+        for(i = 0; i < 9; ++i)
+            ke4(cx->ks, i);
+    }
+#endif
+    ke4(cx->ks, 9);
+    cx->inf.l = 0;
+    cx->inf.b[0] = 10 * 16;
+
+#ifdef USE_VIA_ACE_IF_PRESENT
+    if(VIA_ACE_AVAILABLE)
+        cx->inf.b[1] = 0xff;
+#endif
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined(AES_192) || defined( AES_VAR )
+
+#define kef6(k,i) \
+{   k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \
+    k[6*(i)+ 7] = ss[1] ^= ss[0]; \
+    k[6*(i)+ 8] = ss[2] ^= ss[1]; \
+    k[6*(i)+ 9] = ss[3] ^= ss[2]; \
+}
+
+#define ke6(k,i) \
+{   kef6(k,i); \
+    k[6*(i)+10] = ss[4] ^= ss[3]; \
+    k[6*(i)+11] = ss[5] ^= ss[4]; \
+}
+
+AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1])
+{   uint_32t    ss[6];
+
+    cx->ks[0] = ss[0] = word_in(key, 0);
+    cx->ks[1] = ss[1] = word_in(key, 1);
+    cx->ks[2] = ss[2] = word_in(key, 2);
+    cx->ks[3] = ss[3] = word_in(key, 3);
+    cx->ks[4] = ss[4] = word_in(key, 4);
+    cx->ks[5] = ss[5] = word_in(key, 5);
+
+#ifdef ENC_KS_UNROLL
+    ke6(cx->ks, 0);  ke6(cx->ks, 1);
+    ke6(cx->ks, 2);  ke6(cx->ks, 3);
+    ke6(cx->ks, 4);  ke6(cx->ks, 5);
+    ke6(cx->ks, 6);
+#else
+    {   uint_32t i;
+        for(i = 0; i < 7; ++i)
+            ke6(cx->ks, i);
+    }
+#endif
+    kef6(cx->ks, 7);
+    cx->inf.l = 0;
+    cx->inf.b[0] = 12 * 16;
+
+#ifdef USE_VIA_ACE_IF_PRESENT
+    if(VIA_ACE_AVAILABLE)
+        cx->inf.b[1] = 0xff;
+#endif
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined(AES_256) || defined( AES_VAR )
+
+#define kef8(k,i) \
+{   k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \
+    k[8*(i)+ 9] = ss[1] ^= ss[0]; \
+    k[8*(i)+10] = ss[2] ^= ss[1]; \
+    k[8*(i)+11] = ss[3] ^= ss[2]; \
+}
+
+#define ke8(k,i) \
+{   kef8(k,i); \
+    k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \
+    k[8*(i)+13] = ss[5] ^= ss[4]; \
+    k[8*(i)+14] = ss[6] ^= ss[5]; \
+    k[8*(i)+15] = ss[7] ^= ss[6]; \
+}
+
+AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1])
+{   uint_32t    ss[8];
+
+    cx->ks[0] = ss[0] = word_in(key, 0);
+    cx->ks[1] = ss[1] = word_in(key, 1);
+    cx->ks[2] = ss[2] = word_in(key, 2);
+    cx->ks[3] = ss[3] = word_in(key, 3);
+    cx->ks[4] = ss[4] = word_in(key, 4);
+    cx->ks[5] = ss[5] = word_in(key, 5);
+    cx->ks[6] = ss[6] = word_in(key, 6);
+    cx->ks[7] = ss[7] = word_in(key, 7);
+
+#ifdef ENC_KS_UNROLL
+    ke8(cx->ks, 0); ke8(cx->ks, 1);
+    ke8(cx->ks, 2); ke8(cx->ks, 3);
+    ke8(cx->ks, 4); ke8(cx->ks, 5);
+#else
+    {   uint_32t i;
+        for(i = 0; i < 6; ++i)
+            ke8(cx->ks,  i);
+    }
+#endif
+    kef8(cx->ks, 6);
+    cx->inf.l = 0;
+    cx->inf.b[0] = 14 * 16;
+
+#ifdef USE_VIA_ACE_IF_PRESENT
+    if(VIA_ACE_AVAILABLE)
+        cx->inf.b[1] = 0xff;
+#endif
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_VAR )
+
+AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1])
+{   
+    switch(key_len)
+    {
+    case 16: case 128: return aes_encrypt_key128(key, cx);
+    case 24: case 192: return aes_encrypt_key192(key, cx);
+    case 32: case 256: return aes_encrypt_key256(key, cx);
+    default: return EXIT_FAILURE;
+    }
+}
+
+#endif
+
+#endif
+
+#if (FUNCS_IN_C & DEC_KEYING_IN_C)
+
+/* this is used to store the decryption round keys  */
+/* in forward or reverse order                      */
+
+#ifdef AES_REV_DKS
+#define v(n,i)  ((n) - (i) + 2 * ((i) & 3))
+#else
+#define v(n,i)  (i)
+#endif
+
+#if DEC_ROUND == NO_TABLES
+#define ff(x)   (x)
+#else
+#define ff(x)   inv_mcol(x)
+#if defined( dec_imvars )
+#define d_vars  dec_imvars
+#endif
+#endif
+
+#if defined(AES_128) || defined( AES_VAR )
+
+#define k4e(k,i) \
+{   k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \
+    k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \
+    k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \
+    k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \
+}
+
+#if 1
+
+#define kdf4(k,i) \
+{   ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \
+    ss[1] = ss[1] ^ ss[3]; \
+    ss[2] = ss[2] ^ ss[3]; \
+    ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \
+    ss[i % 4] ^= ss[4]; \
+    ss[4] ^= k[v(40,(4*(i)))];   k[v(40,(4*(i))+4)] = ff(ss[4]); \
+    ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \
+    ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \
+    ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \
+}
+
+#define kd4(k,i) \
+{   ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \
+    ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
+    k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \
+    k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \
+    k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \
+    k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \
+}
+
+#define kdl4(k,i) \
+{   ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
+    k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \
+    k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \
+    k[v(40,(4*(i))+6)] = ss[0]; \
+    k[v(40,(4*(i))+7)] = ss[1]; \
+}
+
+#else
+
+#define kdf4(k,i) \
+{   ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \
+    ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \
+    ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \
+    ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \
+}
+
+#define kd4(k,i) \
+{   ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \
+    ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \
+    ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \
+    ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \
+    ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \
+}
+
+#define kdl4(k,i) \
+{   ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \
+    ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \
+    ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \
+    ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \
+}
+
+#endif
+
+AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1])
+{   uint_32t    ss[5];
+#if defined( d_vars )
+        d_vars;
+#endif
+    cx->ks[v(40,(0))] = ss[0] = word_in(key, 0);
+    cx->ks[v(40,(1))] = ss[1] = word_in(key, 1);
+    cx->ks[v(40,(2))] = ss[2] = word_in(key, 2);
+    cx->ks[v(40,(3))] = ss[3] = word_in(key, 3);
+
+#ifdef DEC_KS_UNROLL
+     kdf4(cx->ks, 0); kd4(cx->ks, 1);
+     kd4(cx->ks, 2);  kd4(cx->ks, 3);
+     kd4(cx->ks, 4);  kd4(cx->ks, 5);
+     kd4(cx->ks, 6);  kd4(cx->ks, 7);
+     kd4(cx->ks, 8);  kdl4(cx->ks, 9);
+#else
+    {   uint_32t i;
+        for(i = 0; i < 10; ++i)
+            k4e(cx->ks, i);
+#if !(DEC_ROUND == NO_TABLES)
+        for(i = N_COLS; i < 10 * N_COLS; ++i)
+            cx->ks[i] = inv_mcol(cx->ks[i]);
+#endif
+    }
+#endif
+    cx->inf.l = 0;
+    cx->inf.b[0] = 10 * 16;
+
+#ifdef USE_VIA_ACE_IF_PRESENT
+    if(VIA_ACE_AVAILABLE)
+        cx->inf.b[1] = 0xff;
+#endif
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined(AES_192) || defined( AES_VAR )
+
+#define k6ef(k,i) \
+{   k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \
+    k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \
+    k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \
+    k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \
+}
+
+#define k6e(k,i) \
+{   k6ef(k,i); \
+    k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \
+    k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \
+}
+
+#define kdf6(k,i) \
+{   ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \
+    ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \
+    ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \
+    ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \
+    ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \
+    ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \
+}
+
+#define kd6(k,i) \
+{   ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \
+    ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \
+    ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \
+    ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \
+    ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \
+    ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \
+    ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \
+}
+
+#define kdl6(k,i) \
+{   ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \
+    ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \
+    ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \
+    ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \
+}
+
+AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1])
+{   uint_32t    ss[7];
+#if defined( d_vars )
+        d_vars;
+#endif
+    cx->ks[v(48,(0))] = ss[0] = word_in(key, 0);
+    cx->ks[v(48,(1))] = ss[1] = word_in(key, 1);
+    cx->ks[v(48,(2))] = ss[2] = word_in(key, 2);
+    cx->ks[v(48,(3))] = ss[3] = word_in(key, 3);
+
+#ifdef DEC_KS_UNROLL
+    cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4));
+    cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5));
+    kdf6(cx->ks, 0); kd6(cx->ks, 1);
+    kd6(cx->ks, 2);  kd6(cx->ks, 3);
+    kd6(cx->ks, 4);  kd6(cx->ks, 5);
+    kd6(cx->ks, 6);  kdl6(cx->ks, 7);
+#else
+    cx->ks[v(48,(4))] = ss[4] = word_in(key, 4);
+    cx->ks[v(48,(5))] = ss[5] = word_in(key, 5);
+    {   uint_32t i;
+
+        for(i = 0; i < 7; ++i)
+            k6e(cx->ks, i);
+        k6ef(cx->ks, 7);
+#if !(DEC_ROUND == NO_TABLES)
+        for(i = N_COLS; i < 12 * N_COLS; ++i)
+            cx->ks[i] = inv_mcol(cx->ks[i]);
+#endif
+    }
+#endif
+    cx->inf.l = 0;
+    cx->inf.b[0] = 12 * 16;
+
+#ifdef USE_VIA_ACE_IF_PRESENT
+    if(VIA_ACE_AVAILABLE)
+        cx->inf.b[1] = 0xff;
+#endif
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined(AES_256) || defined( AES_VAR )
+
+#define k8ef(k,i) \
+{   k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \
+    k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \
+    k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \
+    k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \
+}
+
+#define k8e(k,i) \
+{   k8ef(k,i); \
+    k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \
+    k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \
+    k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \
+    k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \
+}
+
+#define kdf8(k,i) \
+{   ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \
+    ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \
+    ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \
+    ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \
+    ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \
+    ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \
+    ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \
+    ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \
+}
+
+#define kd8(k,i) \
+{   ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \
+    ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \
+    ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \
+    ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \
+    ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \
+    ss[8] = ls_box(ss[3],0); \
+    ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \
+    ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \
+    ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \
+    ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \
+}
+
+#define kdl8(k,i) \
+{   ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \
+    ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \
+    ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \
+    ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \
+}
+
+AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1])
+{   uint_32t    ss[9];
+#if defined( d_vars )
+        d_vars;
+#endif
+    cx->ks[v(56,(0))] = ss[0] = word_in(key, 0);
+    cx->ks[v(56,(1))] = ss[1] = word_in(key, 1);
+    cx->ks[v(56,(2))] = ss[2] = word_in(key, 2);
+    cx->ks[v(56,(3))] = ss[3] = word_in(key, 3);
+
+#ifdef DEC_KS_UNROLL
+    cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4));
+    cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5));
+    cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6));
+    cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7));
+    kdf8(cx->ks, 0); kd8(cx->ks, 1);
+    kd8(cx->ks, 2);  kd8(cx->ks, 3);
+    kd8(cx->ks, 4);  kd8(cx->ks, 5);
+    kdl8(cx->ks, 6);
+#else
+    cx->ks[v(56,(4))] = ss[4] = word_in(key, 4);
+    cx->ks[v(56,(5))] = ss[5] = word_in(key, 5);
+    cx->ks[v(56,(6))] = ss[6] = word_in(key, 6);
+    cx->ks[v(56,(7))] = ss[7] = word_in(key, 7);
+    {   uint_32t i;
+
+        for(i = 0; i < 6; ++i)
+            k8e(cx->ks,  i);
+        k8ef(cx->ks,  6);
+#if !(DEC_ROUND == NO_TABLES)
+        for(i = N_COLS; i < 14 * N_COLS; ++i)
+            cx->ks[i] = inv_mcol(cx->ks[i]);
+#endif
+    }
+#endif
+    cx->inf.l = 0;
+    cx->inf.b[0] = 14 * 16;
+
+#ifdef USE_VIA_ACE_IF_PRESENT
+    if(VIA_ACE_AVAILABLE)
+        cx->inf.b[1] = 0xff;
+#endif
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_VAR )
+
+AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1])
+{
+    switch(key_len)
+    {
+    case 16: case 128: return aes_decrypt_key128(key, cx);
+    case 24: case 192: return aes_decrypt_key192(key, cx);
+    case 32: case 256: return aes_decrypt_key256(key, cx);
+    default: return EXIT_FAILURE;
+    }
+}
+
+#endif
+
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+ cbits/gladman/aesopt.h view
@@ -0,0 +1,746 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+
+ This file contains the compilation options for AES (Rijndael) and code
+ that is common across encryption, key scheduling and table generation.
+
+ OPERATION
+
+ These source code files implement the AES algorithm Rijndael designed by
+ Joan Daemen and Vincent Rijmen. This version is designed for the standard
+ block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24
+ and 32 bytes).
+
+ This version is designed for flexibility and speed using operations on
+ 32-bit words rather than operations on bytes.  It can be compiled with
+ either big or little endian internal byte order but is faster when the
+ native byte order for the processor is used.
+
+ THE CIPHER INTERFACE
+
+ The cipher interface is implemented as an array of bytes in which lower
+ AES bit sequence indexes map to higher numeric significance within bytes.
+
+  uint_8t                 (an unsigned  8-bit type)
+  uint_32t                (an unsigned 32-bit type)
+  struct aes_encrypt_ctx  (structure for the cipher encryption context)
+  struct aes_decrypt_ctx  (structure for the cipher decryption context)
+  AES_RETURN                the function return type
+
+  C subroutine calls:
+
+  AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]);
+  AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]);
+  AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]);
+  AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out,
+                                                  const aes_encrypt_ctx cx[1]);
+
+  AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]);
+  AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]);
+  AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]);
+  AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out,
+                                                  const aes_decrypt_ctx cx[1]);
+
+ IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that
+ you call aes_init() before AES is used so that the tables are initialised.
+
+ C++ aes class subroutines:
+
+     Class AESencrypt  for encryption
+
+      Construtors:
+          AESencrypt(void)
+          AESencrypt(const unsigned char *key) - 128 bit key
+      Members:
+          AES_RETURN key128(const unsigned char *key)
+          AES_RETURN key192(const unsigned char *key)
+          AES_RETURN key256(const unsigned char *key)
+          AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const
+
+      Class AESdecrypt  for encryption
+      Construtors:
+          AESdecrypt(void)
+          AESdecrypt(const unsigned char *key) - 128 bit key
+      Members:
+          AES_RETURN key128(const unsigned char *key)
+          AES_RETURN key192(const unsigned char *key)
+          AES_RETURN key256(const unsigned char *key)
+          AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const
+*/
+
+#if !defined( _AESOPT_H )
+#define _AESOPT_H
+
+#if defined( __cplusplus )
+#include "aescpp.h"
+#else
+#include "aes.h"
+#endif
+
+/*  PLATFORM SPECIFIC INCLUDES */
+
+#include "brg_endian.h"
+
+/*  CONFIGURATION - THE USE OF DEFINES
+
+    Later in this section there are a number of defines that control the
+    operation of the code.  In each section, the purpose of each define is
+    explained so that the relevant form can be included or excluded by
+    setting either 1's or 0's respectively on the branches of the related
+    #if clauses.  The following local defines should not be changed.
+*/
+
+#define ENCRYPTION_IN_C     1
+#define DECRYPTION_IN_C     2
+#define ENC_KEYING_IN_C     4
+#define DEC_KEYING_IN_C     8
+
+#define NO_TABLES           0
+#define ONE_TABLE           1
+#define FOUR_TABLES         4
+#define NONE                0
+#define PARTIAL             1
+#define FULL                2
+
+/*  --- START OF USER CONFIGURED OPTIONS --- */
+
+/*  1. BYTE ORDER WITHIN 32 BIT WORDS
+
+    The fundamental data processing units in Rijndael are 8-bit bytes. The
+    input, output and key input are all enumerated arrays of bytes in which
+    bytes are numbered starting at zero and increasing to one less than the
+    number of bytes in the array in question. This enumeration is only used
+    for naming bytes and does not imply any adjacency or order relationship
+    from one byte to another. When these inputs and outputs are considered
+    as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to
+    byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte.
+    In this implementation bits are numbered from 0 to 7 starting at the
+    numerically least significant end of each byte (bit n represents 2^n).
+
+    However, Rijndael can be implemented more efficiently using 32-bit
+    words by packing bytes into words so that bytes 4*n to 4*n+3 are placed
+    into word[n]. While in principle these bytes can be assembled into words
+    in any positions, this implementation only supports the two formats in
+    which bytes in adjacent positions within words also have adjacent byte
+    numbers. This order is called big-endian if the lowest numbered bytes
+    in words have the highest numeric significance and little-endian if the
+    opposite applies.
+
+    This code can work in either order irrespective of the order used by the
+    machine on which it runs. Normally the internal byte order will be set
+    to the order of the processor on which the code is to be run but this
+    define can be used to reverse this in special situations
+
+    WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set.
+    This define will hence be redefined later (in section 4) if necessary
+*/
+
+#if 1
+#  define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER
+#elif 0
+#  define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN
+#elif 0
+#  define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN
+#else
+#  error The algorithm byte order is not defined
+#endif
+
+/*  2. VIA ACE SUPPORT */
+
+#if defined( __GNUC__ ) && defined( __i386__ ) \
+ || defined( _WIN32   ) && defined( _M_IX86  ) \
+ && !(defined( _WIN64 ) || defined( _WIN32_WCE ) || defined( _MSC_VER ) && ( _MSC_VER <= 800 ))
+#  define VIA_ACE_POSSIBLE
+#endif
+
+/*  Define this option if support for the VIA ACE is required. This uses
+    inline assembler instructions and is only implemented for the Microsoft,
+    Intel and GCC compilers.  If VIA ACE is known to be present, then defining
+    ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption
+    code.  If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if
+    it is detected (both present and enabled) but the normal AES code will
+    also be present.
+
+    When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte
+    aligned; other input/output buffers do not need to be 16 byte aligned
+    but there are very large performance gains if this can be arranged.
+    VIA ACE also requires the decryption key schedule to be in reverse
+    order (which later checks below ensure).
+*/
+
+#if 1 && defined( VIA_ACE_POSSIBLE ) && !defined( USE_VIA_ACE_IF_PRESENT )
+#  define USE_VIA_ACE_IF_PRESENT
+#endif
+
+#if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( ASSUME_VIA_ACE_PRESENT )
+#  define ASSUME_VIA_ACE_PRESENT
+#  endif
+
+/*  3. ASSEMBLER SUPPORT
+
+    This define (which can be on the command line) enables the use of the
+    assembler code routines for encryption, decryption and key scheduling
+    as follows:
+
+    ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for
+                encryption and decryption and but with key scheduling in C
+    ASM_X86_V2  uses assembler (aes_x86_v2.asm) with compressed tables for
+                encryption, decryption and key scheduling
+    ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for
+                encryption and decryption and but with key scheduling in C
+    ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for
+                encryption and decryption and but with key scheduling in C
+
+    Change one 'if 0' below to 'if 1' to select the version or define
+    as a compilation option.
+*/
+
+#if 0 && !defined( ASM_X86_V1C )
+#  define ASM_X86_V1C
+#elif 0 && !defined( ASM_X86_V2  )
+#  define ASM_X86_V2
+#elif 0 && !defined( ASM_X86_V2C )
+#  define ASM_X86_V2C
+#elif 0 && !defined( ASM_AMD64_C )
+#  define ASM_AMD64_C
+#endif
+
+#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \
+      && !defined( _M_IX86 ) || defined( ASM_AMD64_C ) && !defined( _M_X64 )
+#  error Assembler code is only available for x86 and AMD64 systems
+#endif
+
+/*  4. FAST INPUT/OUTPUT OPERATIONS.
+
+    On some machines it is possible to improve speed by transferring the
+    bytes in the input and output arrays to and from the internal 32-bit
+    variables by addressing these arrays as if they are arrays of 32-bit
+    words.  On some machines this will always be possible but there may
+    be a large performance penalty if the byte arrays are not aligned on
+    the normal word boundaries. On other machines this technique will
+    lead to memory access errors when such 32-bit word accesses are not
+    properly aligned. The option SAFE_IO avoids such problems but will
+    often be slower on those machines that support misaligned access
+    (especially so if care is taken to align the input  and output byte
+    arrays on 32-bit word boundaries). If SAFE_IO is not defined it is
+    assumed that access to byte arrays as if they are arrays of 32-bit
+    words will not cause problems when such accesses are misaligned.
+*/
+#if 1 && !defined( _MSC_VER )
+#  define SAFE_IO
+#endif
+
+/*  5. LOOP UNROLLING
+
+    The code for encryption and decrytpion cycles through a number of rounds
+    that can be implemented either in a loop or by expanding the code into a
+    long sequence of instructions, the latter producing a larger program but
+    one that will often be much faster. The latter is called loop unrolling.
+    There are also potential speed advantages in expanding two iterations in
+    a loop with half the number of iterations, which is called partial loop
+    unrolling.  The following options allow partial or full loop unrolling
+    to be set independently for encryption and decryption
+*/
+#if 1
+#  define ENC_UNROLL  FULL
+#elif 0
+#  define ENC_UNROLL  PARTIAL
+#else
+#  define ENC_UNROLL  NONE
+#endif
+
+#if 1
+#  define DEC_UNROLL  FULL
+#elif 0
+#  define DEC_UNROLL  PARTIAL
+#else
+#  define DEC_UNROLL  NONE
+#endif
+
+#if 1
+#  define ENC_KS_UNROLL
+#endif
+
+#if 1
+#  define DEC_KS_UNROLL
+#endif
+
+/*  6. FAST FINITE FIELD OPERATIONS
+
+    If this section is included, tables are used to provide faster finite
+    field arithmetic (this has no effect if FIXED_TABLES is defined).
+*/
+#if 1
+#  define FF_TABLES
+#endif
+
+/*  7. INTERNAL STATE VARIABLE FORMAT
+
+    The internal state of Rijndael is stored in a number of local 32-bit
+    word varaibles which can be defined either as an array or as individual
+    names variables. Include this section if you want to store these local
+    varaibles in arrays. Otherwise individual local variables will be used.
+*/
+#if 1
+#  define ARRAYS
+#endif
+
+/*  8. FIXED OR DYNAMIC TABLES
+
+    When this section is included the tables used by the code are compiled
+    statically into the binary file.  Otherwise the subroutine aes_init()
+    must be called to compute them before the code is first used.
+*/
+#if 1 && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 ))
+#  define FIXED_TABLES
+#endif
+
+/*  9. MASKING OR CASTING FROM LONGER VALUES TO BYTES
+
+    In some systems it is better to mask longer values to extract bytes 
+    rather than using a cast. This option allows this choice.
+*/
+#if 0
+#  define to_byte(x)  ((uint_8t)(x))
+#else
+#  define to_byte(x)  ((x) & 0xff)
+#endif
+
+/*  10. TABLE ALIGNMENT
+
+    On some sytsems speed will be improved by aligning the AES large lookup
+    tables on particular boundaries. This define should be set to a power of
+    two giving the desired alignment. It can be left undefined if alignment
+    is not needed.  This option is specific to the Microsft VC++ compiler -
+    it seems to sometimes cause trouble for the VC++ version 6 compiler.
+*/
+
+#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 )
+#  define TABLE_ALIGN 32
+#endif
+
+/*  11.  REDUCE CODE AND TABLE SIZE
+
+    This replaces some expanded macros with function calls if AES_ASM_V2 or
+    AES_ASM_V2C are defined
+*/
+
+#if 1 && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))
+#  define REDUCE_CODE_SIZE
+#endif
+
+/*  12. TABLE OPTIONS
+
+    This cipher proceeds by repeating in a number of cycles known as 'rounds'
+    which are implemented by a round function which can optionally be speeded
+    up using tables.  The basic tables are each 256 32-bit words, with either
+    one or four tables being required for each round function depending on
+    how much speed is required. The encryption and decryption round functions
+    are different and the last encryption and decrytpion round functions are
+    different again making four different round functions in all.
+
+    This means that:
+      1. Normal encryption and decryption rounds can each use either 0, 1
+         or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
+      2. The last encryption and decryption rounds can also use either 0, 1
+         or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
+
+    Include or exclude the appropriate definitions below to set the number
+    of tables used by this implementation.
+*/
+
+#if 1   /* set tables for the normal encryption round */
+#  define ENC_ROUND   FOUR_TABLES
+#elif 0
+#  define ENC_ROUND   ONE_TABLE
+#else
+#  define ENC_ROUND   NO_TABLES
+#endif
+
+#if 1   /* set tables for the last encryption round */
+#  define LAST_ENC_ROUND  FOUR_TABLES
+#elif 0
+#  define LAST_ENC_ROUND  ONE_TABLE
+#else
+#  define LAST_ENC_ROUND  NO_TABLES
+#endif
+
+#if 1   /* set tables for the normal decryption round */
+#  define DEC_ROUND   FOUR_TABLES
+#elif 0
+#  define DEC_ROUND   ONE_TABLE
+#else
+#  define DEC_ROUND   NO_TABLES
+#endif
+
+#if 1   /* set tables for the last decryption round */
+#  define LAST_DEC_ROUND  FOUR_TABLES
+#elif 0
+#  define LAST_DEC_ROUND  ONE_TABLE
+#else
+#  define LAST_DEC_ROUND  NO_TABLES
+#endif
+
+/*  The decryption key schedule can be speeded up with tables in the same
+    way that the round functions can.  Include or exclude the following
+    defines to set this requirement.
+*/
+#if 1
+#  define KEY_SCHED   FOUR_TABLES
+#elif 0
+#  define KEY_SCHED   ONE_TABLE
+#else
+#  define KEY_SCHED   NO_TABLES
+#endif
+
+/*  ---- END OF USER CONFIGURED OPTIONS ---- */
+
+/* VIA ACE support is only available for VC++ and GCC */
+
+#if !defined( _MSC_VER ) && !defined( __GNUC__ )
+#  if defined( ASSUME_VIA_ACE_PRESENT )
+#    undef ASSUME_VIA_ACE_PRESENT
+#  endif
+#  if defined( USE_VIA_ACE_IF_PRESENT )
+#    undef USE_VIA_ACE_IF_PRESENT
+#  endif
+#endif
+
+#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT )
+#  define USE_VIA_ACE_IF_PRESENT
+#endif
+
+#if defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS )
+#  define AES_REV_DKS
+#endif
+
+/* Assembler support requires the use of platform byte order */
+
+#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \
+    && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER)
+#  undef  ALGORITHM_BYTE_ORDER
+#  define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER
+#endif
+
+/* In this implementation the columns of the state array are each held in
+   32-bit words. The state array can be held in various ways: in an array
+   of words, in a number of individual word variables or in a number of
+   processor registers. The following define maps a variable name x and
+   a column number c to the way the state array variable is to be held.
+   The first define below maps the state into an array x[c] whereas the
+   second form maps the state into a number of individual variables x0,
+   x1, etc.  Another form could map individual state colums to machine
+   register names.
+*/
+
+#if defined( ARRAYS )
+#  define s(x,c) x[c]
+#else
+#  define s(x,c) x##c
+#endif
+
+/*  This implementation provides subroutines for encryption, decryption
+    and for setting the three key lengths (separately) for encryption
+    and decryption. Since not all functions are needed, masks are set
+    up here to determine which will be implemented in C
+*/
+
+#if !defined( AES_ENCRYPT )
+#  define EFUNCS_IN_C   0
+#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \
+    || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C )
+#  define EFUNCS_IN_C   ENC_KEYING_IN_C
+#elif !defined( ASM_X86_V2 )
+#  define EFUNCS_IN_C   ( ENCRYPTION_IN_C | ENC_KEYING_IN_C )
+#else
+#  define EFUNCS_IN_C   0
+#endif
+
+#if !defined( AES_DECRYPT )
+#  define DFUNCS_IN_C   0
+#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \
+    || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C )
+#  define DFUNCS_IN_C   DEC_KEYING_IN_C
+#elif !defined( ASM_X86_V2 )
+#  define DFUNCS_IN_C   ( DECRYPTION_IN_C | DEC_KEYING_IN_C )
+#else
+#  define DFUNCS_IN_C   0
+#endif
+
+#define FUNCS_IN_C  ( EFUNCS_IN_C | DFUNCS_IN_C )
+
+/* END OF CONFIGURATION OPTIONS */
+
+#define RC_LENGTH   (5 * (AES_BLOCK_SIZE / 4 - 2))
+
+/* Disable or report errors on some combinations of options */
+
+#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES
+#  undef  LAST_ENC_ROUND
+#  define LAST_ENC_ROUND  NO_TABLES
+#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES
+#  undef  LAST_ENC_ROUND
+#  define LAST_ENC_ROUND  ONE_TABLE
+#endif
+
+#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE
+#  undef  ENC_UNROLL
+#  define ENC_UNROLL  NONE
+#endif
+
+#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES
+#  undef  LAST_DEC_ROUND
+#  define LAST_DEC_ROUND  NO_TABLES
+#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES
+#  undef  LAST_DEC_ROUND
+#  define LAST_DEC_ROUND  ONE_TABLE
+#endif
+
+#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE
+#  undef  DEC_UNROLL
+#  define DEC_UNROLL  NONE
+#endif
+
+#if defined( bswap32 )
+#  define aes_sw32    bswap32
+#elif defined( bswap_32 )
+#  define aes_sw32    bswap_32
+#else
+#  define brot(x,n)   (((uint_32t)(x) <<  n) | ((uint_32t)(x) >> (32 - n)))
+#  define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00))
+#endif
+
+/*  upr(x,n):  rotates bytes within words by n positions, moving bytes to
+               higher index positions with wrap around into low positions
+    ups(x,n):  moves bytes by n positions to higher index positions in
+               words but without wrap around
+    bval(x,n): extracts a byte from a word
+
+    WARNING:   The definitions given here are intended only for use with
+               unsigned variables and with shift counts that are compile
+               time constants
+*/
+
+#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN )
+#  define upr(x,n)      (((uint_32t)(x) << (8 * (n))) | ((uint_32t)(x) >> (32 - 8 * (n))))
+#  define ups(x,n)      ((uint_32t) (x) << (8 * (n)))
+#  define bval(x,n)     to_byte((x) >> (8 * (n)))
+#  define bytes2word(b0, b1, b2, b3)  \
+        (((uint_32t)(b3) << 24) | ((uint_32t)(b2) << 16) | ((uint_32t)(b1) << 8) | (b0))
+#endif
+
+#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN )
+#  define upr(x,n)      (((uint_32t)(x) >> (8 * (n))) | ((uint_32t)(x) << (32 - 8 * (n))))
+#  define ups(x,n)      ((uint_32t) (x) >> (8 * (n)))
+#  define bval(x,n)     to_byte((x) >> (24 - 8 * (n)))
+#  define bytes2word(b0, b1, b2, b3)  \
+        (((uint_32t)(b0) << 24) | ((uint_32t)(b1) << 16) | ((uint_32t)(b2) << 8) | (b3))
+#endif
+
+#if defined( SAFE_IO )
+#  define word_in(x,c)    bytes2word(((const uint_8t*)(x)+4*c)[0], ((const uint_8t*)(x)+4*c)[1], \
+                                   ((const uint_8t*)(x)+4*c)[2], ((const uint_8t*)(x)+4*c)[3])
+#  define word_out(x,c,v) { ((uint_8t*)(x)+4*c)[0] = bval(v,0); ((uint_8t*)(x)+4*c)[1] = bval(v,1); \
+                          ((uint_8t*)(x)+4*c)[2] = bval(v,2); ((uint_8t*)(x)+4*c)[3] = bval(v,3); }
+#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER )
+#  define word_in(x,c)    (*((uint_32t*)(x)+(c)))
+#  define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = (v))
+#else
+#  define word_in(x,c)    aes_sw32(*((uint_32t*)(x)+(c)))
+#  define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = aes_sw32(v))
+#endif
+
+/* the finite field modular polynomial and elements */
+
+#define WPOLY   0x011b
+#define BPOLY     0x1b
+
+/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+#define m1  0x80808080
+#define m2  0x7f7f7f7f
+#define gf_mulx(x)  ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY))
+
+/* The following defines provide alternative definitions of gf_mulx that might
+   give improved performance if a fast 32-bit multiply is not available. Note
+   that a temporary variable u needs to be defined where gf_mulx is used.
+
+#define gf_mulx(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6))
+#define m4  (0x01010101 * BPOLY)
+#define gf_mulx(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4)
+*/
+
+/* Work out which tables are needed for the different options   */
+
+#if defined( ASM_X86_V1C )
+#  if defined( ENC_ROUND )
+#    undef  ENC_ROUND
+#  endif
+#  define ENC_ROUND   FOUR_TABLES
+#  if defined( LAST_ENC_ROUND )
+#    undef  LAST_ENC_ROUND
+#  endif
+#  define LAST_ENC_ROUND  FOUR_TABLES
+#  if defined( DEC_ROUND )
+#    undef  DEC_ROUND
+#  endif
+#  define DEC_ROUND   FOUR_TABLES
+#  if defined( LAST_DEC_ROUND )
+#    undef  LAST_DEC_ROUND
+#  endif
+#  define LAST_DEC_ROUND  FOUR_TABLES
+#  if defined( KEY_SCHED )
+#    undef  KEY_SCHED
+#    define KEY_SCHED   FOUR_TABLES
+#  endif
+#endif
+
+#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C )
+#  if ENC_ROUND == ONE_TABLE
+#    define FT1_SET
+#  elif ENC_ROUND == FOUR_TABLES
+#    define FT4_SET
+#  else
+#    define SBX_SET
+#  endif
+#  if LAST_ENC_ROUND == ONE_TABLE
+#    define FL1_SET
+#  elif LAST_ENC_ROUND == FOUR_TABLES
+#    define FL4_SET
+#  elif !defined( SBX_SET )
+#    define SBX_SET
+#  endif
+#endif
+
+#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C )
+#  if DEC_ROUND == ONE_TABLE
+#    define IT1_SET
+#  elif DEC_ROUND == FOUR_TABLES
+#    define IT4_SET
+#  else
+#    define ISB_SET
+#  endif
+#  if LAST_DEC_ROUND == ONE_TABLE
+#    define IL1_SET
+#  elif LAST_DEC_ROUND == FOUR_TABLES
+#    define IL4_SET
+#  elif !defined(ISB_SET)
+#    define ISB_SET
+#  endif
+#endif
+
+#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )))
+#  if ((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C))
+#    if KEY_SCHED == ONE_TABLE
+#      if !defined( FL1_SET )  && !defined( FL4_SET ) 
+#        define LS1_SET
+#      endif
+#    elif KEY_SCHED == FOUR_TABLES
+#      if !defined( FL4_SET )
+#        define LS4_SET
+#      endif
+#    elif !defined( SBX_SET )
+#      define SBX_SET
+#    endif
+#  endif
+#  if (FUNCS_IN_C & DEC_KEYING_IN_C)
+#    if KEY_SCHED == ONE_TABLE
+#      define IM1_SET
+#    elif KEY_SCHED == FOUR_TABLES
+#      define IM4_SET
+#    elif !defined( SBX_SET )
+#      define SBX_SET
+#    endif
+#  endif
+#endif
+
+/* generic definitions of Rijndael macros that use tables    */
+
+#define no_table(x,box,vf,rf,c) bytes2word( \
+    box[bval(vf(x,0,c),rf(0,c))], \
+    box[bval(vf(x,1,c),rf(1,c))], \
+    box[bval(vf(x,2,c),rf(2,c))], \
+    box[bval(vf(x,3,c),rf(3,c))])
+
+#define one_table(x,op,tab,vf,rf,c) \
+ (     tab[bval(vf(x,0,c),rf(0,c))] \
+  ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
+  ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
+  ^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
+
+#define four_tables(x,tab,vf,rf,c) \
+ (  tab[0][bval(vf(x,0,c),rf(0,c))] \
+  ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
+  ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
+  ^ tab[3][bval(vf(x,3,c),rf(3,c))])
+
+#define vf1(x,r,c)  (x)
+#define rf1(r,c)    (r)
+#define rf2(r,c)    ((8+r-c)&3)
+
+/* perform forward and inverse column mix operation on four bytes in long word x in */
+/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros.  */
+
+#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) 
+
+#if defined( FM4_SET )      /* not currently used */
+#  define fwd_mcol(x)       four_tables(x,t_use(f,m),vf1,rf1,0)
+#elif defined( FM1_SET )    /* not currently used */
+#  define fwd_mcol(x)       one_table(x,upr,t_use(f,m),vf1,rf1,0)
+#else
+#  define dec_fmvars        uint_32t g2
+#  define fwd_mcol(x)       (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1))
+#endif
+
+#if defined( IM4_SET )
+#  define inv_mcol(x)       four_tables(x,t_use(i,m),vf1,rf1,0)
+#elif defined( IM1_SET )
+#  define inv_mcol(x)       one_table(x,upr,t_use(i,m),vf1,rf1,0)
+#else
+#  define dec_imvars        uint_32t g2, g4, g9
+#  define inv_mcol(x)       (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \
+                            (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1))
+#endif
+
+#if defined( FL4_SET )
+#  define ls_box(x,c)       four_tables(x,t_use(f,l),vf1,rf2,c)
+#elif defined( LS4_SET )
+#  define ls_box(x,c)       four_tables(x,t_use(l,s),vf1,rf2,c)
+#elif defined( FL1_SET )
+#  define ls_box(x,c)       one_table(x,upr,t_use(f,l),vf1,rf2,c)
+#elif defined( LS1_SET )
+#  define ls_box(x,c)       one_table(x,upr,t_use(l,s),vf1,rf2,c)
+#else
+#  define ls_box(x,c)       no_table(x,t_use(s,box),vf1,rf2,c)
+#endif
+
+#endif
+
+#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET )
+#  define ISB_SET
+#endif
+
+#endif
+ cbits/gladman/aestab.c view
@@ -0,0 +1,398 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+*/
+
+#define DO_TABLES
+
+#include "aes.h"
+#include "aesopt.h"
+
+#if defined(FIXED_TABLES)
+
+#define sb_data(w) {\
+    w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+    w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+    w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+    w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+    w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+    w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+    w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+    w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+    w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+    w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+    w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+    w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+    w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+    w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+    w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+    w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+    w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+    w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+    w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+    w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+    w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+    w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+    w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+    w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+    w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+    w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+    w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+    w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+    w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+    w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+    w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+    w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
+
+#define isb_data(w) {\
+    w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
+    w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
+    w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
+    w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
+    w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
+    w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
+    w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
+    w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
+    w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
+    w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
+    w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
+    w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
+    w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
+    w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
+    w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
+    w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
+    w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
+    w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
+    w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
+    w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
+    w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
+    w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
+    w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
+    w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
+    w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
+    w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
+    w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
+    w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
+    w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
+    w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
+    w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
+    w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
+
+#define mm_data(w) {\
+    w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
+    w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
+    w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
+    w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
+    w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
+    w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
+    w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
+    w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
+    w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
+    w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
+    w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
+    w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
+    w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
+    w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
+    w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
+    w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
+    w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
+    w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
+    w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
+    w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
+    w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
+    w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
+    w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
+    w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
+    w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
+    w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
+    w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
+    w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
+    w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
+    w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
+    w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
+    w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
+
+#define rc_data(w) {\
+    w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\
+    w(0x1b), w(0x36) }
+
+#define h0(x)   (x)
+
+#define w0(p)   bytes2word(p, 0, 0, 0)
+#define w1(p)   bytes2word(0, p, 0, 0)
+#define w2(p)   bytes2word(0, 0, p, 0)
+#define w3(p)   bytes2word(0, 0, 0, p)
+
+#define u0(p)   bytes2word(f2(p), p, p, f3(p))
+#define u1(p)   bytes2word(f3(p), f2(p), p, p)
+#define u2(p)   bytes2word(p, f3(p), f2(p), p)
+#define u3(p)   bytes2word(p, p, f3(p), f2(p))
+
+#define v0(p)   bytes2word(fe(p), f9(p), fd(p), fb(p))
+#define v1(p)   bytes2word(fb(p), fe(p), f9(p), fd(p))
+#define v2(p)   bytes2word(fd(p), fb(p), fe(p), f9(p))
+#define v3(p)   bytes2word(f9(p), fd(p), fb(p), fe(p))
+
+#endif
+
+#if defined(FIXED_TABLES) || !defined(FF_TABLES)
+
+#define f2(x)   ((x<<1) ^ (((x>>7) & 1) * WPOLY))
+#define f4(x)   ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
+#define f8(x)   ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \
+                        ^ (((x>>5) & 4) * WPOLY))
+#define f3(x)   (f2(x) ^ x)
+#define f9(x)   (f8(x) ^ x)
+#define fb(x)   (f8(x) ^ f2(x) ^ x)
+#define fd(x)   (f8(x) ^ f4(x) ^ x)
+#define fe(x)   (f8(x) ^ f4(x) ^ f2(x))
+
+#else
+
+#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
+#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
+#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
+#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
+#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
+#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
+
+#endif
+
+#include "aestab.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+#if defined(FIXED_TABLES)
+
+/* implemented in case of wrong call for fixed tables */
+
+AES_RETURN aes_init(void)
+{
+    return EXIT_SUCCESS;
+}
+
+#else   /*  Generate the tables for the dynamic table option */
+
+#if defined(FF_TABLES)
+
+#define gf_inv(x)   ((x) ? pow[ 255 - log[x]] : 0)
+
+#else 
+
+/*  It will generally be sensible to use tables to compute finite
+    field multiplies and inverses but where memory is scarse this
+    code might sometimes be better. But it only has effect during
+    initialisation so its pretty unimportant in overall terms.
+*/
+
+/*  return 2 ^ (n - 1) where n is the bit number of the highest bit
+    set in x with x in the range 1 < x < 0x00000200.   This form is
+    used so that locals within fi can be bytes rather than words
+*/
+
+static uint_8t hibit(const uint_32t x)
+{   uint_8t r = (uint_8t)((x >> 1) | (x >> 2));
+
+    r |= (r >> 2);
+    r |= (r >> 4);
+    return (r + 1) >> 1;
+}
+
+/* return the inverse of the finite field element x */
+
+static uint_8t gf_inv(const uint_8t x)
+{   uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
+
+    if(x < 2) 
+        return x;
+
+    for( ; ; )
+    {
+        if(n1)
+            while(n2 >= n1)             /* divide polynomial p2 by p1    */
+            {
+                n2 /= n1;               /* shift smaller polynomial left */ 
+                p2 ^= (p1 * n2) & 0xff; /* and remove from larger one    */
+                v2 ^= v1 * n2;          /* shift accumulated value and   */ 
+                n2 = hibit(p2);         /* add into result               */
+            }
+        else
+            return v1;
+
+        if(n2)                          /* repeat with values swapped    */ 
+            while(n1 >= n2)
+            {
+                n1 /= n2; 
+                p1 ^= p2 * n1; 
+                v1 ^= v2 * n1; 
+                n1 = hibit(p1);
+            }
+        else
+            return v2;
+    }
+}
+
+#endif
+
+/* The forward and inverse affine transformations used in the S-box */
+uint_8t fwd_affine(const uint_8t x)
+{   uint_32t w = x;
+    w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
+    return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
+}
+
+uint_8t inv_affine(const uint_8t x)
+{   uint_32t w = x;
+    w = (w << 1) ^ (w << 3) ^ (w << 6);
+    return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
+}
+
+static int init = 0;
+
+AES_RETURN aes_init(void)
+{   uint_32t  i, w;
+
+#if defined(FF_TABLES)
+
+    uint_8t  pow[512], log[256];
+
+    if(init)
+        return EXIT_SUCCESS;
+    /*  log and power tables for GF(2^8) finite field with
+        WPOLY as modular polynomial - the simplest primitive
+        root is 0x03, used here to generate the tables
+    */
+
+    i = 0; w = 1;
+    do
+    {
+        pow[i] = (uint_8t)w;
+        pow[i + 255] = (uint_8t)w;
+        log[w] = (uint_8t)i++;
+        w ^=  (w << 1) ^ (w & 0x80 ? WPOLY : 0);
+    }
+    while (w != 1);
+
+#else
+    if(init)
+        return EXIT_SUCCESS;
+#endif
+
+    for(i = 0, w = 1; i < RC_LENGTH; ++i)
+    {
+        t_set(r,c)[i] = bytes2word(w, 0, 0, 0);
+        w = f2(w);
+    }
+
+    for(i = 0; i < 256; ++i)
+    {   uint_8t    b;
+
+        b = fwd_affine(gf_inv((uint_8t)i));
+        w = bytes2word(f2(b), b, b, f3(b));
+
+#if defined( SBX_SET )
+        t_set(s,box)[i] = b;
+#endif
+
+#if defined( FT1_SET )                 /* tables for a normal encryption round */
+        t_set(f,n)[i] = w;
+#endif
+#if defined( FT4_SET )
+        t_set(f,n)[0][i] = w;
+        t_set(f,n)[1][i] = upr(w,1);
+        t_set(f,n)[2][i] = upr(w,2);
+        t_set(f,n)[3][i] = upr(w,3);
+#endif
+        w = bytes2word(b, 0, 0, 0);
+
+#if defined( FL1_SET )            /* tables for last encryption round (may also   */
+        t_set(f,l)[i] = w;        /* be used in the key schedule)                 */
+#endif
+#if defined( FL4_SET )
+        t_set(f,l)[0][i] = w;
+        t_set(f,l)[1][i] = upr(w,1);
+        t_set(f,l)[2][i] = upr(w,2);
+        t_set(f,l)[3][i] = upr(w,3);
+#endif
+
+#if defined( LS1_SET )			/* table for key schedule if t_set(f,l) above is*/
+        t_set(l,s)[i] = w;      /* not of the required form                     */
+#endif
+#if defined( LS4_SET )
+        t_set(l,s)[0][i] = w;
+        t_set(l,s)[1][i] = upr(w,1);
+        t_set(l,s)[2][i] = upr(w,2);
+        t_set(l,s)[3][i] = upr(w,3);
+#endif
+
+        b = gf_inv(inv_affine((uint_8t)i));
+        w = bytes2word(fe(b), f9(b), fd(b), fb(b));
+
+#if defined( IM1_SET )			/* tables for the inverse mix column operation  */
+        t_set(i,m)[b] = w;
+#endif
+#if defined( IM4_SET )
+        t_set(i,m)[0][b] = w;
+        t_set(i,m)[1][b] = upr(w,1);
+        t_set(i,m)[2][b] = upr(w,2);
+        t_set(i,m)[3][b] = upr(w,3);
+#endif
+
+#if defined( ISB_SET )
+        t_set(i,box)[i] = b;
+#endif
+#if defined( IT1_SET )			/* tables for a normal decryption round */
+        t_set(i,n)[i] = w;
+#endif
+#if defined( IT4_SET )
+        t_set(i,n)[0][i] = w;
+        t_set(i,n)[1][i] = upr(w,1);
+        t_set(i,n)[2][i] = upr(w,2);
+        t_set(i,n)[3][i] = upr(w,3);
+#endif
+        w = bytes2word(b, 0, 0, 0);
+#if defined( IL1_SET )			/* tables for last decryption round */
+        t_set(i,l)[i] = w;
+#endif
+#if defined( IL4_SET )
+        t_set(i,l)[0][i] = w;
+        t_set(i,l)[1][i] = upr(w,1);
+        t_set(i,l)[2][i] = upr(w,2);
+        t_set(i,l)[3][i] = upr(w,3);
+#endif
+    }
+    init = 1;
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+ cbits/gladman/aestab.h view
@@ -0,0 +1,180 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+
+ This file contains the code for declaring the tables needed to implement
+ AES. The file aesopt.h is assumed to be included before this header file.
+ If there are no global variables, the definitions here can be used to put
+ the AES tables in a structure so that a pointer can then be added to the
+ AES context to pass them to the AES routines that need them.   If this
+ facility is used, the calling program has to ensure that this pointer is
+ managed appropriately.  In particular, the value of the t_dec(in,it) item
+ in the table structure must be set to zero in order to ensure that the
+ tables are initialised. In practice the three code sequences in aeskey.c
+ that control the calls to aes_init() and the aes_init() routine itself will
+ have to be changed for a specific implementation. If global variables are
+ available it will generally be preferable to use them with the precomputed
+ FIXED_TABLES option that uses static global tables.
+
+ The following defines can be used to control the way the tables
+ are defined, initialised and used in embedded environments that
+ require special features for these purposes
+
+    the 't_dec' construction is used to declare fixed table arrays
+    the 't_set' construction is used to set fixed table values
+    the 't_use' construction is used to access fixed table values
+
+    256 byte tables:
+
+        t_xxx(s,box)    => forward S box
+        t_xxx(i,box)    => inverse S box
+
+    256 32-bit word OR 4 x 256 32-bit word tables:
+
+        t_xxx(f,n)      => forward normal round
+        t_xxx(f,l)      => forward last round
+        t_xxx(i,n)      => inverse normal round
+        t_xxx(i,l)      => inverse last round
+        t_xxx(l,s)      => key schedule table
+        t_xxx(i,m)      => key schedule table
+
+    Other variables and tables:
+
+        t_xxx(r,c)      => the rcon table
+*/
+
+#if !defined( _AESTAB_H )
+#define _AESTAB_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define t_dec(m,n) t_##m##n
+#define t_set(m,n) t_##m##n
+#define t_use(m,n) t_##m##n
+
+#if defined(FIXED_TABLES)
+#  if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ ))
+/*   make tables far data to avoid using too much DGROUP space (PG) */
+#    define CONST const far
+#  else
+#    define CONST const
+#  endif
+#else
+#  define CONST
+#endif
+
+#if defined(DO_TABLES)
+#  define EXTERN
+#else
+#  define EXTERN extern
+#endif
+
+#if defined(_MSC_VER) && defined(TABLE_ALIGN)
+#define ALIGN __declspec(align(TABLE_ALIGN))
+#else
+#define ALIGN
+#endif
+
+#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 )
+#  define XP_DIR __cdecl
+#else
+#  define XP_DIR
+#endif
+
+#if defined(DO_TABLES) && defined(FIXED_TABLES)
+#define d_1(t,n,b,e)       EXTERN ALIGN CONST XP_DIR t n[256]    =   b(e)
+#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) }
+EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0);
+#else
+#define d_1(t,n,b,e)       EXTERN ALIGN CONST XP_DIR t n[256]
+#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256]
+EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH];
+#endif
+
+#if defined( SBX_SET )
+    d_1(uint_8t, t_dec(s,box), sb_data, h0);
+#endif
+#if defined( ISB_SET )
+    d_1(uint_8t, t_dec(i,box), isb_data, h0);
+#endif
+
+#if defined( FT1_SET )
+    d_1(uint_32t, t_dec(f,n), sb_data, u0);
+#endif
+#if defined( FT4_SET )
+    d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3);
+#endif
+
+#if defined( FL1_SET )
+    d_1(uint_32t, t_dec(f,l), sb_data, w0);
+#endif
+#if defined( FL4_SET )
+    d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3);
+#endif
+
+#if defined( IT1_SET )
+    d_1(uint_32t, t_dec(i,n), isb_data, v0);
+#endif
+#if defined( IT4_SET )
+    d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3);
+#endif
+
+#if defined( IL1_SET )
+    d_1(uint_32t, t_dec(i,l), isb_data, w0);
+#endif
+#if defined( IL4_SET )
+    d_4(uint_32t, t_dec(i,l), isb_data, w0, w1, w2, w3);
+#endif
+
+#if defined( LS1_SET )
+#if defined( FL1_SET )
+#undef  LS1_SET
+#else
+    d_1(uint_32t, t_dec(l,s), sb_data, w0);
+#endif
+#endif
+
+#if defined( LS4_SET )
+#if defined( FL4_SET )
+#undef  LS4_SET
+#else
+    d_4(uint_32t, t_dec(l,s), sb_data, w0, w1, w2, w3);
+#endif
+#endif
+
+#if defined( IM1_SET )
+    d_1(uint_32t, t_dec(i,m), mm_data, v0);
+#endif
+#if defined( IM4_SET )
+    d_4(uint_32t, t_dec(i,m), mm_data, v0, v1, v2, v3);
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+ cbits/gladman/brg_endian.h view
@@ -0,0 +1,133 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+*/
+
+#ifndef _BRG_ENDIAN_H
+#define _BRG_ENDIAN_H
+
+#define IS_BIG_ENDIAN      4321 /* byte 0 is most significant (mc68k) */
+#define IS_LITTLE_ENDIAN   1234 /* byte 0 is least significant (i386) */
+
+/* Include files where endian defines and byteswap functions may reside */
+#if defined( __sun )
+#  include <sys/isa_defs.h>
+#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
+#  include <sys/endian.h>
+#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
+      defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
+#  include <machine/endian.h>
+#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
+#  if !defined( __MINGW32__ ) && !defined( _AIX )
+#    include <endian.h>
+#    if !defined( __BEOS__ )
+#      include <byteswap.h>
+#    endif
+#  endif
+#endif
+
+/* Now attempt to set the define for platform byte order using any  */
+/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which  */
+/* seem to encompass most endian symbol definitions                 */
+
+#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
+#  if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
+#    define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#  elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
+#    define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#  endif
+#elif defined( BIG_ENDIAN )
+#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#elif defined( LITTLE_ENDIAN )
+#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#endif
+
+#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
+#  if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
+#    define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#  elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
+#    define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#  endif
+#elif defined( _BIG_ENDIAN )
+#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#elif defined( _LITTLE_ENDIAN )
+#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#endif
+
+#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
+#  if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
+#    define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#  elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
+#    define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#  endif
+#elif defined( __BIG_ENDIAN )
+#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#elif defined( __LITTLE_ENDIAN )
+#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#endif
+
+#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
+#  if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
+#    define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#  elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
+#    define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#  endif
+#elif defined( __BIG_ENDIAN__ )
+#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#elif defined( __LITTLE_ENDIAN__ )
+#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#endif
+
+/*  if the platform byte order could not be determined, then try to */
+/*  set this define using common machine defines                    */
+#if !defined(PLATFORM_BYTE_ORDER)
+
+#if   defined( __alpha__ ) || defined( __alpha ) || defined( i386 )       || \
+      defined( __i386__ )  || defined( _M_I86 )  || defined( _M_IX86 )    || \
+      defined( __OS2__ )   || defined( sun386 )  || defined( __TURBOC__ ) || \
+      defined( vax )       || defined( vms )     || defined( VMS )        || \
+      defined( __VMS )     || defined( _M_X64 )
+#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+
+#elif defined( AMIGA )   || defined( applec )    || defined( __AS400__ )  || \
+      defined( _CRAY )   || defined( __hppa )    || defined( __hp9000 )   || \
+      defined( ibm370 )  || defined( mc68000 )   || defined( m68k )       || \
+      defined( __MRC__ ) || defined( __MVS__ )   || defined( __MWERKS__ ) || \
+      defined( sparc )   || defined( __sparc)    || defined( SYMANTEC_C ) || \
+      defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM )   || \
+      defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
+#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+
+#elif 0     /* **** EDIT HERE IF NECESSARY **** */
+#  define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
+#elif 0     /* **** EDIT HERE IF NECESSARY **** */
+#  define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+#else
+#  error Please edit lines 126 or 128 in brg_endian.h to set the platform byte order
+#endif
+
+#endif
+
+#endif
+ cbits/gladman/brg_types.h view
@@ -0,0 +1,226 @@+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue Date: 20/12/2007
+
+ The unsigned integer types defined here are of the form uint_<nn>t where
+ <nn> is the length of the type; for example, the unsigned 32-bit type is
+ 'uint_32t'.  These are NOT the same as the 'C99 integer types' that are
+ defined in the inttypes.h and stdint.h headers since attempts to use these
+ types have shown that support for them is still highly variable.  However,
+ since the latter are of the form uint<nn>_t, a regular expression search
+ and replace (in VC++ search on 'uint_{:z}t' and replace with 'uint\1_t')
+ can be used to convert the types used here to the C99 standard types.
+*/
+
+#ifndef _BRG_TYPES_H
+#define _BRG_TYPES_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <limits.h>
+
+#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 )
+#  include <stddef.h>
+#  define ptrint_t intptr_t
+#elif defined( __ECOS__ )
+#  define intptr_t unsigned int
+#  define ptrint_t intptr_t
+#elif defined( __GNUC__ ) && ( __GNUC__ >= 3 )
+#  include <stdint.h>
+#  define ptrint_t intptr_t
+#else
+#  define ptrint_t int
+#endif
+
+#ifndef BRG_UI8
+#  define BRG_UI8
+#  if UCHAR_MAX == 255u
+     typedef unsigned char uint_8t;
+#  else
+#    error Please define uint_8t as an 8-bit unsigned integer type in brg_types.h
+#  endif
+#endif
+
+#ifndef BRG_UI16
+#  define BRG_UI16
+#  if USHRT_MAX == 65535u
+     typedef unsigned short uint_16t;
+#  else
+#    error Please define uint_16t as a 16-bit unsigned short type in brg_types.h
+#  endif
+#endif
+
+#ifndef BRG_UI32
+#  define BRG_UI32
+#  if UINT_MAX == 4294967295u
+#    define li_32(h) 0x##h##u
+     typedef unsigned int uint_32t;
+#  elif ULONG_MAX == 4294967295u
+#    define li_32(h) 0x##h##ul
+     typedef unsigned long uint_32t;
+#  elif defined( _CRAY )
+#    error This code needs 32-bit data types, which Cray machines do not provide
+#  else
+#    error Please define uint_32t as a 32-bit unsigned integer type in brg_types.h
+#  endif
+#endif
+
+#ifndef BRG_UI64
+#  if defined( __BORLANDC__ ) && !defined( __MSDOS__ )
+#    define BRG_UI64
+#    define li_64(h) 0x##h##ui64
+     typedef unsigned __int64 uint_64t;
+#  elif defined( _MSC_VER ) && ( _MSC_VER < 1300 )    /* 1300 == VC++ 7.0 */
+#    define BRG_UI64
+#    define li_64(h) 0x##h##ui64
+     typedef unsigned __int64 uint_64t;
+#  elif defined( __sun ) && defined( ULONG_MAX ) && ULONG_MAX == 0xfffffffful
+#    define BRG_UI64
+#    define li_64(h) 0x##h##ull
+     typedef unsigned long long uint_64t;
+#  elif defined( __MVS__ )
+#    define BRG_UI64
+#    define li_64(h) 0x##h##ull
+     typedef unsigned int long long uint_64t;
+#  elif defined( UINT_MAX ) && UINT_MAX > 4294967295u
+#    if UINT_MAX == 18446744073709551615u
+#      define BRG_UI64
+#      define li_64(h) 0x##h##u
+       typedef unsigned int uint_64t;
+#    endif
+#  elif defined( ULONG_MAX ) && ULONG_MAX > 4294967295u
+#    if ULONG_MAX == 18446744073709551615ul
+#      define BRG_UI64
+#      define li_64(h) 0x##h##ul
+       typedef unsigned long uint_64t;
+#    endif
+#  elif defined( ULLONG_MAX ) && ULLONG_MAX > 4294967295u
+#    if ULLONG_MAX == 18446744073709551615ull
+#      define BRG_UI64
+#      define li_64(h) 0x##h##ull
+       typedef unsigned long long uint_64t;
+#    endif
+#  elif defined( ULONG_LONG_MAX ) && ULONG_LONG_MAX > 4294967295u
+#    if ULONG_LONG_MAX == 18446744073709551615ull
+#      define BRG_UI64
+#      define li_64(h) 0x##h##ull
+       typedef unsigned long long uint_64t;
+#    endif
+#  endif
+#endif
+
+#if !defined( BRG_UI64 )
+#  if defined( NEED_UINT_64T )
+#    error Please define uint_64t as an unsigned 64 bit type in brg_types.h
+#  endif
+#endif
+
+#ifndef RETURN_VALUES
+#  define RETURN_VALUES
+#  if defined( DLL_EXPORT )
+#    if defined( _MSC_VER ) || defined ( __INTEL_COMPILER )
+#      define VOID_RETURN    __declspec( dllexport ) void __stdcall
+#      define INT_RETURN     __declspec( dllexport ) int  __stdcall
+#    elif defined( __GNUC__ )
+#      define VOID_RETURN    __declspec( __dllexport__ ) void
+#      define INT_RETURN     __declspec( __dllexport__ ) int
+#    else
+#      error Use of the DLL is only available on the Microsoft, Intel and GCC compilers
+#    endif
+#  elif defined( DLL_IMPORT )
+#    if defined( _MSC_VER ) || defined ( __INTEL_COMPILER )
+#      define VOID_RETURN    __declspec( dllimport ) void __stdcall
+#      define INT_RETURN     __declspec( dllimport ) int  __stdcall
+#    elif defined( __GNUC__ )
+#      define VOID_RETURN    __declspec( __dllimport__ ) void
+#      define INT_RETURN     __declspec( __dllimport__ ) int
+#    else
+#      error Use of the DLL is only available on the Microsoft, Intel and GCC compilers
+#    endif
+#  elif defined( __WATCOMC__ )
+#    define VOID_RETURN  void __cdecl
+#    define INT_RETURN   int  __cdecl
+#  else
+#    define VOID_RETURN  void
+#    define INT_RETURN   int
+#  endif
+#endif
+
+/*	These defines are used to detect and set the memory alignment of pointers.
+    Note that offsets are in bytes.
+
+	ALIGN_OFFSET(x,n)			return the positive or zero offset of 
+								the memory addressed by the pointer 'x' 
+								from an address that is aligned on an 
+								'n' byte boundary ('n' is a power of 2)
+
+	ALIGN_FLOOR(x,n)			return a pointer that points to memory
+								that is aligned on an 'n' byte boundary 
+								and is not higher than the memory address
+								pointed to by 'x' ('n' is a power of 2)
+
+	ALIGN_CEIL(x,n)				return a pointer that points to memory
+								that is aligned on an 'n' byte boundary 
+								and is not lower than the memory address
+								pointed to by 'x' ('n' is a power of 2)
+*/
+
+#define ALIGN_OFFSET(x,n)	(((ptrint_t)(x)) & ((n) - 1))
+#define ALIGN_FLOOR(x,n)	((uint_8t*)(x) - ( ((ptrint_t)(x)) & ((n) - 1)))
+#define ALIGN_CEIL(x,n)		((uint_8t*)(x) + (-((ptrint_t)(x)) & ((n) - 1)))
+
+/*  These defines are used to declare buffers in a way that allows
+    faster operations on longer variables to be used.  In all these
+    defines 'size' must be a power of 2 and >= 8. NOTE that the 
+    buffer size is in bytes but the type length is in bits
+
+    UNIT_TYPEDEF(x,size)        declares a variable 'x' of length 
+                                'size' bits
+
+    BUFR_TYPEDEF(x,size,bsize)  declares a buffer 'x' of length 'bsize' 
+                                bytes defined as an array of variables
+                                each of 'size' bits (bsize must be a 
+                                multiple of size / 8)
+
+    UNIT_CAST(x,size)           casts a variable to a type of 
+                                length 'size' bits
+
+    UPTR_CAST(x,size)           casts a pointer to a pointer to a 
+                                varaiable of length 'size' bits
+*/
+
+#define UI_TYPE(size)               uint_##size##t
+#define UNIT_TYPEDEF(x,size)        typedef UI_TYPE(size) x
+#define BUFR_TYPEDEF(x,size,bsize)  typedef UI_TYPE(size) x[bsize / (size >> 3)]
+#define UNIT_CAST(x,size)           ((UI_TYPE(size) )(x))  
+#define UPTR_CAST(x,size)           ((UI_TYPE(size)*)(x))
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+ cbits/gladman/ctr_inc.c view
@@ -0,0 +1,17 @@+#include "brg_types.h"+#include "aesopt.h"+#include "ctr_inc.h"+#include <stdio.h>++#if AES_BLOCK_SIZE != 16+# error AES block size wrong ?!+#endif++void ctr_inc(unsigned char *cbuf) {+  uint_64t *ctr = (uint_64t*)cbuf;+  int word;+  for (word = 0; word < 2; word++) {+    ctr[word]++;+    if (ctr[word]) break;+  }+}
+ cbits/gladman/ctr_inc.h view
@@ -0,0 +1,1 @@+void ctr_inc(unsigned char *);
+ intel-aes.cabal view
@@ -0,0 +1,126 @@+Name:           intel-aes+Version:        0.1.1++License:                BSD3+License-file:           LICENSE+Stability:              Beta+Maintainer:		Ryan Newton <rrnewton@gmail.com>+Author:			Ryan Newton <rrnewton@gmail.com>, Svein Ove Aas <svein.ove@aas.no>, Thomas M. DuBuisson+Copyright:              Copyright (c) 2011 Intel Corporation+Synopsis:               Hardware accelerated AES encryption and RNG.+Description: +  AES encryption with optional hardware acceleration.  Plus,+  statistically sound, splittable random number generation based on AES.++  The package is nothing more than a wrapper around the following Intel-provided AESNI+  sample library that also includes a portable software implementation by Brian Gladman:++    http://software.intel.com/en-us/articles/download-the-intel-aesni-sample-library/++  The consists of C, assembly sources, and Haskell sources.  It+  includes prebuilt dynamic libraries for these sources to make the+  build process less fragile.  (Rebuilding requires the @yasm@+  assembler.)  But prebuilt shared libraries are not included for all+  platforms yet.  (Volunteers needed!)++  Regarding portability, see:++    https://github.com/rrnewton/intel-aes/issues/#issue/1++  Finally, note that this package is currently triggering some haddock+  problems. A manually built copy of the documentation can be found+  at:++    http://people.csail.mit.edu/newton/intel-aes-doc/++-- Here are some example results from an Intel X5680 processor.++--  How many random numbers can we generate in a second on one thread?+-- 	  First, timing with System.Random interface:+-- 	     14,482,725 random ints generated [System.Random stdGen]    +-- 		 16,061 random ints generated [PureHaskell/reference]   +-- 		 32,309 random ints generated [PureHaskell]             +-- 	      2,401,893 random ints generated [Gladman inefficient]     +-- 	     15,980,625 random ints generated [Gladman]                 +-- 	      2,329,500 random ints generated [IntelAES inefficient]    +-- 	     32,383,799 random ints generated [IntelAES]                +-- 	 Comparison to C's rand():+-- 	     71,347,778 random ints generated [rand in Haskell loop]    ++++Category: Cryptography+Cabal-Version: >=1.8+Tested-With: GHC == 7.0.1+-- Portability:            Untested on Windows.++build-type: Custom++extra-source-files:+      cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/Makefile+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x64/do_rdtsc.s+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x64/iaesx64.s+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x86/do_rdtsc.s+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x86/iaesx86.s+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/include/iaes_asm_interface.h+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/include/iaesni.h+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/mk_lnx_lib.sh+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/mk_win_lib.bat+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/aessample.c+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/aessampletiming.cpp+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/intel_aes.c+    , cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_license.txt+    , cbits/Makefile+    , cbits/c_test.c++    -- Including the gladman implementation for now as well:+    , cbits/gladman/aes.h, cbits/gladman/aesopt.h, cbits/gladman/aestab.h+    , cbits/gladman/brg_endian.h, cbits/gladman/brg_types.h, cbits/gladman/aes.txt+    , cbits/gladman/aes_via_ace.h, cbits/gladman/ctr_inc.h+++source-repository head+  type:     git+  location: git://github.com/rrnewton/intel-aes.git+++----------------------------------------------------------------------------------------------------+library+  build-depends:  base >= 4 && < 5, random, DRBG, split, process, haskell98, time,+                  DRBG, crypto-api, bytestring, cereal, tagged++  exposed-modules:  Codec.Encryption.BurtonRNGSlow+                 ,  Codec.Crypto.IntelAES+                 ,  Codec.Crypto.IntelAES.AESNI+                 ,  Codec.Crypto.ConvertRNG+--                 ,  Codec.Crypto.IntelAES.GladmanAES+                 ,  Codec.Crypto.GladmanAES+  other-modules:    Data.LargeWord +                 ,  Benchmark.BinSearch+                 ,  Codec.Encryption.AES+                 ,  Codec.Encryption.AESAux+                 ,  Codec.Utils+  GHC-Options: -O2 +  extra-libraries: intel_aes++  -- The gladman sources are straightforward and can be built by Cabal (unlike the intel C/asm)+  C-sources: cbits/gladman/aescrypt.c, cbits/gladman/aeskey.c, cbits/gladman/aestab.c,+             cbits/gladman/aes_modes.c, cbits/gladman/ctr_inc.c+  Include-Dirs: cbits++++-- ----------------------------------------------------------------------------------------------------+Executable benchmark-intel-aes-rng+  Main-is:        SimpleRNGBench.hs+  Build-Depends:  base >= 4 && < 5, split, rdtsc, unix, random, crypto-api, DRBG+                , tagged, cereal, bytestring, process, haskell98, time+--                , AES+                , intel-aes+  GHC-Options:    -O2 -threaded -rtsopts +  C-sources:	   cbits/c_test.c+  Include-dirs:    cbits++++--  cabal haddock --hoogle --executables --hyperlink-source --haddock-options="--html"