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 +155/−0
- Codec/Crypto/ConvertRNG.hs +182/−0
- Codec/Crypto/GladmanAES.hsc +194/−0
- Codec/Crypto/IntelAES.hs +125/−0
- Codec/Crypto/IntelAES/AESNI.hs +289/−0
- Codec/Encryption/AES.hs +64/−0
- Codec/Encryption/AESAux.hs +1008/−0
- Codec/Encryption/BurtonRNGSlow.hs +83/−0
- Codec/Utils.hs +138/−0
- Data/LargeWord.hs +153/−0
- LICENSE +38/−0
- Setup.hs +157/−0
- SimpleRNGBench.hs +363/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/Makefile +48/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x64/do_rdtsc.s +37/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x64/iaesx64.s +2054/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x86/do_rdtsc.s +35/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/asm/x86/iaesx86.s +2183/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/include/iaes_asm_interface.h +126/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/include/iaesni.h +151/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/mk_lnx_lib.sh +43/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/mk_win_lib.bat +35/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/aessample.c +302/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/aessampletiming.cpp +541/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/src/intel_aes.c +308/−0
- cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_license.txt +34/−0
- cbits/Makefile +9/−0
- cbits/c_test.c +55/−0
- cbits/gladman/aes.h +205/−0
- cbits/gladman/aes.txt +556/−0
- cbits/gladman/aes_modes.c +945/−0
- cbits/gladman/aes_via_ace.h +529/−0
- cbits/gladman/aescrypt.c +301/−0
- cbits/gladman/aeskey.c +555/−0
- cbits/gladman/aesopt.h +746/−0
- cbits/gladman/aestab.c +398/−0
- cbits/gladman/aestab.h +180/−0
- cbits/gladman/brg_endian.h +133/−0
- cbits/gladman/brg_types.h +226/−0
- cbits/gladman/ctr_inc.c +17/−0
- cbits/gladman/ctr_inc.h +1/−0
- intel-aes.cabal +126/−0
+ 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"