cipher-aes128-0.7.0.3/0000755000000000000000000000000012761471030012321 5ustar0000000000000000cipher-aes128-0.7.0.3/AUTHORS0000644000000000000000000000023012761471030013364 0ustar0000000000000000Thomas DuBuisson: Haskell code, refactoring of aes C code (extract mutable portion of GCM struct) Vincent Hanquez: C AES implementations for x86 and NI cipher-aes128-0.7.0.3/cipher-aes128.cabal0000644000000000000000000000650112761471030015562 0ustar0000000000000000-- Initial cipher.cabal generated by cabal init. For further -- documentation, see http://haskell.org/cabal/users-guide/ name: cipher-aes128 version: 0.7.0.3 synopsis: AES and common modes using AES-NI when available. description: Cipher-aes128 is an implementation of AES and common modes of operation. It borrows Hanquez's C AES code (see 'cipher-aes') but is unique due to including compile-time detection of NI compiler support, a slightly more functional interface for GCM operations, exposure of 'Ptr' based operations via the .Internal module, and build-in crypto-api support. Cipher-aes128 was originally developed as "'cipher-aes' plus trampolines", which has since been adopted into cipher-aes. license: BSD3 license-file: LICENSE author: Thomas M. DuBuisson, Vincent Hanquez (See AUTHORS file) maintainer: thomas.dubuisson@gmail.com copyright: Thomas M. DuBuisson category: Cryptography homepage: https://github.com/TomMD/cipher-aes128 bug-reports: https://github.com/TomMD/cipher-aes128/issues build-type: Custom -- build-type: Simple -- ^^^ For HaLVM cabal-version: >=1.10 tested-with: GHC==7.10.3 extra-source-files: ./cbits/*.h, ./cbits/*.c , AUTHORS , cbits/LICENSE flag test description: Build a program to test the AES implementation default: False flag halvm description: The HaLVM target default: False library default-language: Haskell2010 exposed-modules: Crypto.Cipher.AES128, Crypto.Cipher.AES128.Internal build-depends: base >=4.2 && < 5, bytestring >= 0.10.2, crypto-api >= 0.13, tagged, cereal ghc-options: -Wall -O2 c-sources: ./cbits/aes.c , ./cbits/aes_generic.c , ./cbits/aes_x86ni.c , ./cbits/cpu.c , ./cbits/gf.c include-dirs: cbits/ cc-options: if flag(halvm) cc-options: -maes -mpclmul -mssse3 -DWITH_AESNI cpp-options: -DWITH_AESNI -maes -mpclmul -mssse3 -- None by default cc-options: -mssse3 -maes -mpclmul source-repository head type: git location: https://github.com/TomMD/cipher-aes128 benchmark bench type: exitcode-stdio-1.0 hs-source-dirs: . Benchmark main-is: bench.hs build-depends: base < 5, criterion, crypto-api, entropy, bytestring, tagged, cereal ghc-options: -O2 include-dirs: cbits default-language: Haskell2010 c-sources: ./cbits/aes.c , ./cbits/aes_generic.c , ./cbits/aes_x86ni.c , ./cbits/cpu.c , ./cbits/gf.c cc-options: -mssse3 -maes -mpclmul Executable aes128_test if !flag(test) buildable: False main-is: Test/test.hs if flag(test) build-depends: base , crypto-api-tests , test-framework , cipher-aes128 , bytestring >= 0.10.2 , tagged, cereal, crypto-api cipher-aes128-0.7.0.3/LICENSE0000644000000000000000000000266312761471030013335 0ustar0000000000000000Copyright (c) Thomas DuBuisson All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the author nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cipher-aes128-0.7.0.3/Setup.hs0000644000000000000000000000634112761471030013761 0ustar0000000000000000{-# LANGUAGE CPP #-} import Control.Monad (unless) import Distribution.Simple import Distribution.Simple.LocalBuildInfo import Distribution.Simple.Utils import Distribution.Simple.Program import Distribution.Verbosity import System.Process import System.Exit import System.IO (hFlush, stdout) main :: IO () main = defaultMainWithHooks hk where hk = simpleUserHooks { buildHook = \pd lbi uh bf -> do let ccProg = Program "gcc" undefined undefined undefined hcProg = Program "ghc" undefined undefined undefined mConf = lookupProgram ccProg (withPrograms lbi) hcConf = lookupProgram hcProg (withPrograms lbi) err = error "Could not determine C compiler" _cc = locationPath . programLocation . maybe err id $ mConf hc = locationPath . programLocation . maybe err id $ hcConf b <- canUseAesIntrinsicsFlag hc let newWithPrograms1 = userSpecifyArgs "gcc" aesArgs (withPrograms lbi) newWithPrograms = userSpecifyArgs "ghc" aesArgsHC newWithPrograms1 lbiNew = if b then (lbi {withPrograms = newWithPrograms }) else lbi buildHook simpleUserHooks pd lbiNew uh bf } aesArgs :: [String] aesArgs = ["-mpclmul", "-maes", "-mssse3", "-DHAVE_AES_INTRINSICS", "-DWITH_AESNI"] aesArgsHC :: [String] aesArgsHC = map ("-optc" ++) aesArgs canUseAesIntrinsicsFlag :: FilePath -> IO Bool canUseAesIntrinsicsFlag cc = do withTempDirectory normal "" "testIntrinsic" $ \tmpDir -> do writeFile (tmpDir ++ "/testIntrinsic.c") (unlines [ "#include " , "int real_main() {" , "return 0; }" ]) ec <- myRawSystemExitCode normal cc (aesArgsHC ++ ["-c", tmpDir ++ "/testIntrinsic.c"]) notice normal $ "Result of NI Intrinsics Test: " ++ show (ec == ExitSuccess) return (ec == ExitSuccess) myRawSystemExitCode :: Verbosity -> FilePath -> [String] -> IO ExitCode #if __GLASGOW_HASKELL__ >= 704 -- We know for sure, that if GHC >= 7.4 implies Cabal >= 1.14 myRawSystemExitCode = rawSystemExitCode #else -- Legacy branch: -- We implement our own 'rawSystemExitCode', this will even work if -- the user happens to have Cabal >= 1.14 installed with GHC 7.0 or -- 7.2 myRawSystemExitCode verbosity path args = do printRawCommandAndArgs verbosity path args hFlush stdout exitcode <- rawSystem path args unless (exitcode == ExitSuccess) $ do debug verbosity $ path ++ " returned " ++ show exitcode return exitcode where printRawCommandAndArgs :: Verbosity -> FilePath -> [String] -> IO () printRawCommandAndArgs verbosity path args | verbosity >= deafening = print (path, args) | verbosity >= verbose = putStrLn $ unwords (path : args) | otherwise = return () #endif cipher-aes128-0.7.0.3/Benchmark/0000755000000000000000000000000012761471030014213 5ustar0000000000000000cipher-aes128-0.7.0.3/Benchmark/bench.hs0000644000000000000000000000100412761471030015621 0ustar0000000000000000import qualified Crypto.Cipher.AES128 as AES128 import Crypto.Classes import Crypto.Types import Criterion import Criterion.Main import System.Entropy import Data.Serialize import qualified Data.ByteString as B main = do let iv = zeroIV ivV = B.replicate 16 0 pt <- getEntropy (2^16) k <- buildKeyIO :: IO AES128.AESKey128 defaultMain [ bench "aes-ecb cipher-aes128" $ nf (AES128.encryptBlock k) pt , bench "aes-ctr cipher-aes128" $ nf (fst . AES128.ctr k iv) pt ] cipher-aes128-0.7.0.3/cbits/0000755000000000000000000000000012761471030013425 5ustar0000000000000000cipher-aes128-0.7.0.3/cbits/aes.c0000644000000000000000000005752412761471030014356 0ustar0000000000000000/* * Copyright (c) 2012 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "cpu.h" #include "aes.h" #include "aes_generic.h" #include "bitfn.h" #include #include #include #include "gf.h" #include "aes_x86ni.h" void tmd_aes_generic_encrypt_ecb(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_decrypt_ecb(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_encrypt_cbc(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_decrypt_cbc(aes_block *output, const aes_key *key, const aes_block *ivini, aes_block *newIV, const aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_encrypt_ctr(uint8_t *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const uint8_t *input, uint32_t length); void tmd_aes_generic_encrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_decrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks); void tmd_aes_generic_gcm_encrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX); void tmd_aes_generic_gcm_decrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX); enum { /* init */ INIT_128, INIT_192, INIT_256, /* single block */ ENCRYPT_BLOCK_128, ENCRYPT_BLOCK_192, ENCRYPT_BLOCK_256, DECRYPT_BLOCK_128, DECRYPT_BLOCK_192, DECRYPT_BLOCK_256, /* ecb */ ENCRYPT_ECB_128, ENCRYPT_ECB_192, ENCRYPT_ECB_256, DECRYPT_ECB_128, DECRYPT_ECB_192, DECRYPT_ECB_256, /* cbc */ ENCRYPT_CBC_128, ENCRYPT_CBC_192, ENCRYPT_CBC_256, DECRYPT_CBC_128, DECRYPT_CBC_192, DECRYPT_CBC_256, /* ctr */ ENCRYPT_CTR_128, ENCRYPT_CTR_192, ENCRYPT_CTR_256, /* xts */ ENCRYPT_XTS_128, ENCRYPT_XTS_192, ENCRYPT_XTS_256, DECRYPT_XTS_128, DECRYPT_XTS_192, DECRYPT_XTS_256, /* xts */ ENCRYPT_GCM_128, ENCRYPT_GCM_192, ENCRYPT_GCM_256, DECRYPT_GCM_128, DECRYPT_GCM_192, DECRYPT_GCM_256, }; void *tmd_branch_table[] = { /* INIT */ [INIT_128] = tmd_aes_generic_init, [INIT_192] = tmd_aes_generic_init, [INIT_256] = tmd_aes_generic_init, /* BLOCK */ [ENCRYPT_BLOCK_128] = tmd_aes_generic_encrypt_block, [ENCRYPT_BLOCK_192] = tmd_aes_generic_encrypt_block, [ENCRYPT_BLOCK_256] = tmd_aes_generic_encrypt_block, [DECRYPT_BLOCK_128] = tmd_aes_generic_decrypt_block, [DECRYPT_BLOCK_192] = tmd_aes_generic_decrypt_block, [DECRYPT_BLOCK_256] = tmd_aes_generic_decrypt_block, /* ECB */ [ENCRYPT_ECB_128] = tmd_aes_generic_encrypt_ecb, [ENCRYPT_ECB_192] = tmd_aes_generic_encrypt_ecb, [ENCRYPT_ECB_256] = tmd_aes_generic_encrypt_ecb, [DECRYPT_ECB_128] = tmd_aes_generic_decrypt_ecb, [DECRYPT_ECB_192] = tmd_aes_generic_decrypt_ecb, [DECRYPT_ECB_256] = tmd_aes_generic_decrypt_ecb, /* CBC */ [ENCRYPT_CBC_128] = tmd_aes_generic_encrypt_cbc, [ENCRYPT_CBC_192] = tmd_aes_generic_encrypt_cbc, [ENCRYPT_CBC_256] = tmd_aes_generic_encrypt_cbc, [DECRYPT_CBC_128] = tmd_aes_generic_decrypt_cbc, [DECRYPT_CBC_192] = tmd_aes_generic_decrypt_cbc, [DECRYPT_CBC_256] = tmd_aes_generic_decrypt_cbc, /* CTR */ [ENCRYPT_CTR_128] = tmd_aes_generic_encrypt_ctr, [ENCRYPT_CTR_192] = tmd_aes_generic_encrypt_ctr, [ENCRYPT_CTR_256] = tmd_aes_generic_encrypt_ctr, /* XTS */ [ENCRYPT_XTS_128] = tmd_aes_generic_encrypt_xts, [ENCRYPT_XTS_192] = tmd_aes_generic_encrypt_xts, [ENCRYPT_XTS_256] = tmd_aes_generic_encrypt_xts, [DECRYPT_XTS_128] = tmd_aes_generic_decrypt_xts, [DECRYPT_XTS_192] = tmd_aes_generic_decrypt_xts, [DECRYPT_XTS_256] = tmd_aes_generic_decrypt_xts, /* GCM */ [ENCRYPT_GCM_128] = tmd_aes_generic_gcm_encrypt, [ENCRYPT_GCM_192] = tmd_aes_generic_gcm_encrypt, [ENCRYPT_GCM_256] = tmd_aes_generic_gcm_encrypt, [DECRYPT_GCM_128] = tmd_aes_generic_gcm_decrypt, [DECRYPT_GCM_192] = tmd_aes_generic_gcm_decrypt, [DECRYPT_GCM_256] = tmd_aes_generic_gcm_decrypt, }; typedef void (*init_f)(aes_key *, const uint8_t *, uint8_t); typedef void (*ecb_f)(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks); typedef void (*cbc_f)(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *niv, const aes_block *input, uint32_t nb_blocks); typedef void (*ctr_f)(uint8_t *output, const aes_key *key, const aes_block *iv, aes_block *niv, const uint8_t *input, uint32_t length); typedef void (*xts_f)(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks); typedef void (*gcm_crypt_f)(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX); typedef void (*block_f)(aes_block *output, const aes_key *key, const aes_block *input); #ifdef WITH_AESNI #define GET_INIT(strength) \ ((init_f) (tmd_branch_table[INIT_128 + strength])) #define GET_ECB_ENCRYPT(strength) \ ((ecb_f) (tmd_branch_table[ENCRYPT_ECB_128 + strength])) #define GET_ECB_DECRYPT(strength) \ ((ecb_f) (tmd_branch_table[DECRYPT_ECB_128 + strength])) #define GET_CBC_ENCRYPT(strength) \ ((cbc_f) (tmd_branch_table[ENCRYPT_CBC_128 + strength])) #define GET_CBC_DECRYPT(strength) \ ((cbc_f) (tmd_branch_table[DECRYPT_CBC_128 + strength])) #define GET_CTR_ENCRYPT(strength) \ ((ctr_f) (tmd_branch_table[ENCRYPT_CTR_128 + strength])) #define GET_XTS_ENCRYPT(strength) \ ((xts_f) (tmd_branch_table[ENCRYPT_XTS_128 + strength])) #define GET_XTS_DECRYPT(strength) \ ((xts_f) (tmd_branch_table[DECRYPT_XTS_128 + strength])) #define GET_GCM_ENCRYPT(strength) \ ((gcm_crypt_f) (tmd_branch_table[ENCRYPT_GCM_128 + strength])) #define GET_GCM_DECRYPT(strength) \ ((gcm_crypt_f) (tmd_branch_table[DECRYPT_GCM_128 + strength])) #define aes_encrypt_block(o,k,i) \ (((block_f) (tmd_branch_table[ENCRYPT_BLOCK_128 + k->strength]))(o,k,i)) #define aes_decrypt_block(o,k,i) \ (((block_f) (tmd_branch_table[DECRYPT_BLOCK_128 + k->strength]))(o,k,i)) #else #define GET_INIT(strength) tmd_aes_generic_init #define GET_ECB_ENCRYPT(strength) tmd_aes_generic_encrypt_ecb #define GET_ECB_DECRYPT(strength) tmd_aes_generic_decrypt_ecb #define GET_CBC_ENCRYPT(strength) tmd_aes_generic_encrypt_cbc #define GET_CBC_DECRYPT(strength) tmd_aes_generic_decrypt_cbc #define GET_CTR_ENCRYPT(strength) tmd_aes_generic_encrypt_ctr #define GET_XTS_ENCRYPT(strength) tmd_aes_generic_encrypt_xts #define GET_XTS_DECRYPT(strength) tmd_aes_generic_decrypt_xts #define GET_GCM_ENCRYPT(strength) tmd_aes_generic_gcm_encrypt #define GET_GCM_DECRYPT(strength) tmd_aes_generic_gcm_decrypt #define aes_encrypt_block(o,k,i) tmd_aes_generic_encrypt_block(o,k,i) #define aes_decrypt_block(o,k,i) tmd_aes_generic_decrypt_block(o,k,i) #endif #if defined(ARCH_X86) && defined(WITH_AESNI) void tmd_initialize_table_ni(int aesni, int pclmul) { if (!aesni) return; tmd_branch_table[INIT_128] = tmd_aes_ni_init; tmd_branch_table[INIT_256] = tmd_aes_ni_init; tmd_branch_table[ENCRYPT_BLOCK_128] = tmd_aes_ni_encrypt_block128; tmd_branch_table[DECRYPT_BLOCK_128] = tmd_aes_ni_decrypt_block128; tmd_branch_table[ENCRYPT_BLOCK_256] = tmd_aes_ni_encrypt_block256; tmd_branch_table[DECRYPT_BLOCK_256] = tmd_aes_ni_decrypt_block256; /* ECB */ tmd_branch_table[ENCRYPT_ECB_128] = tmd_aes_ni_encrypt_ecb128; tmd_branch_table[DECRYPT_ECB_128] = tmd_aes_ni_decrypt_ecb128; tmd_branch_table[ENCRYPT_ECB_256] = tmd_aes_ni_encrypt_ecb256; tmd_branch_table[DECRYPT_ECB_256] = tmd_aes_ni_decrypt_ecb256; /* CBC */ tmd_branch_table[ENCRYPT_CBC_128] = tmd_aes_ni_encrypt_cbc128; tmd_branch_table[DECRYPT_CBC_128] = tmd_aes_ni_decrypt_cbc128; tmd_branch_table[ENCRYPT_CBC_256] = tmd_aes_ni_encrypt_cbc256; tmd_branch_table[DECRYPT_CBC_256] = tmd_aes_ni_decrypt_cbc256; /* CTR */ tmd_branch_table[ENCRYPT_CTR_128] = tmd_aes_ni_encrypt_ctr128; tmd_branch_table[ENCRYPT_CTR_256] = tmd_aes_ni_encrypt_ctr256; /* XTS */ tmd_branch_table[ENCRYPT_XTS_128] = tmd_aes_ni_encrypt_xts128; tmd_branch_table[ENCRYPT_XTS_256] = tmd_aes_ni_encrypt_xts256; /* GCM */ tmd_branch_table[ENCRYPT_GCM_128] = tmd_aes_ni_gcm_encrypt128; tmd_branch_table[ENCRYPT_GCM_256] = tmd_aes_ni_gcm_encrypt256; // tmd_branch_table[DECRYPT_GCM_128] = tmd_aes_ni_gcm_decrypt128; // tmd_branch_table[DECRYPT_GCM_256] = tmd_aes_ni_gcm_decrypt256; } #endif aes_key *tmd_allocatekey() { aes_key *res = (aes_key *)malloc(sizeof(aes_key)); return res; } aes_ctx *tmd_allocatectx() { aes_ctx *res = (aes_ctx *)malloc(sizeof(aes_ctx)); return res; } aes_gcm *tmd_allocategcm() { aes_gcm *res = (aes_gcm *)malloc(sizeof(aes_gcm)); return res; } void tmd_freekey(aes_key *k) { free(k); } void tmd_freectx(aes_ctx *c) { free(c); } void tmd_freegcm(aes_gcm *g) { free(g); } void tmd_aes_initkey(aes_key *key, uint8_t *origkey, uint8_t size) { switch (size) { case 16: key->nbr = 10; key->strength = 0; break; case 24: key->nbr = 12; key->strength = 1; break; case 32: key->nbr = 14; key->strength = 2; break; } #if defined(ARCH_X86) && defined(WITH_AESNI) tmd_initialize_hw(tmd_initialize_table_ni); #endif init_f _init = GET_INIT(key->strength); _init(key, origkey, size); } void tmd_aes_encrypt_ecb(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks) { ecb_f e = GET_ECB_ENCRYPT(key->strength); e(output, key, input, nb_blocks); } void tmd_aes_decrypt_ecb(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks) { ecb_f d = GET_ECB_DECRYPT(key->strength); d(output, key, input, nb_blocks); } void tmd_aes_encrypt_cbc(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *niv, const aes_block *input, uint32_t nb_blocks) { cbc_f e = GET_CBC_ENCRYPT(key->strength); e(output, key, iv, niv, input, nb_blocks); } void tmd_aes_decrypt_cbc(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *niv, const aes_block *input, uint32_t nb_blocks) { cbc_f d = GET_CBC_DECRYPT(key->strength); d(output, key, iv, niv, input, nb_blocks); } void tmd_aes_gen_ctr(aes_block *output, const aes_key *key, aes_block *iv, uint32_t nb_blocks) { aes_block block; /* preload IV in block */ block128_copy(&block, iv); for ( ; nb_blocks-- > 0; output++, block128_inc_be(&block)) { aes_encrypt_block(output, key, &block); } } void tmd_aes_encrypt_ctr(uint8_t *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const uint8_t *input, uint32_t len) { ctr_f e = GET_CTR_ENCRYPT(key->strength); e(output, key, iv, newIV, input, len); } void tmd_aes_encrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks) { xts_f e = GET_XTS_ENCRYPT(k1->strength); e(output, k1, k2, dataunit, spoint, input, nb_blocks); } void tmd_aes_decrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks) { tmd_aes_generic_decrypt_xts(output, k1, k2, dataunit, spoint, input, nb_blocks); } void tmd_aes_gcm_encrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX) { gcm_crypt_f e = GET_GCM_ENCRYPT(key->strength); e(output, gcm, ctx, key, input, length, newCTX); } void tmd_aes_gcm_decrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX) { gcm_crypt_f d = GET_GCM_DECRYPT(key->strength); d(output, gcm, ctx, key, input, length, newCTX); } static void gcm_ghash_add(const aes_gcm *gcm, aes_ctx *ctx, const block128 *b) { block128_xor(&ctx->tag, b); tmd_gf_mul(&ctx->tag, &gcm->h); } void tmd_aes_gcm_init(aes_gcm *gcm, const aes_key *key) { block128_zero(&gcm->h); /* prepare H : encrypt_K(0^128) */ aes_encrypt_block(&gcm->h, key, &gcm->h); } void tmd_aes_ctx_init(const aes_gcm *gcm, aes_ctx *ctx , const aes_key *key, const uint8_t *iv, uint32_t len) { ctx->length_aad = 0; ctx->length_input = 0; block128_zero(&ctx->tag); block128_zero(&ctx->iv); if (len == 12) { block128_copy_bytes(&ctx->iv, iv, 12); ctx->iv.b[15] = 0x01; } else { uint32_t origlen = len << 3; int i; for (; len >= 16; len -= 16, iv += 16) { block128_xor(&ctx->iv, (block128 *) iv); tmd_gf_mul(&ctx->iv, &gcm->h); } if (len > 0) { block128_xor_bytes(&ctx->iv, iv, len); tmd_gf_mul(&ctx->iv, &gcm->h); } for (i = 15; origlen; --i, origlen >>= 8) ctx->iv.b[i] ^= (uint8_t) origlen; tmd_gf_mul(&ctx->iv, &gcm->h); } block128_copy(&ctx->civ, &ctx->iv); } void tmd_aes_gcm_aad(const aes_gcm *gcm, aes_ctx *ctx, const uint8_t *input, uint32_t length) { ctx->length_aad += length; for (; length >= 16; input += 16, length -= 16) { gcm_ghash_add(gcm, ctx, (block128 *) input); } if (length > 0) { aes_block tmp; block128_zero(&tmp); block128_copy_bytes(&tmp, input, length); gcm_ghash_add(gcm, ctx, &tmp); } } void tmd_aes_gcm_finish(uint8_t *tag, const aes_gcm *gcm, const aes_key *key, aes_ctx *ctx) { aes_block lblock; int i; /* tag = (tag-1 xor (lenbits(a) | lenbits(c)) ) . H */ lblock.q[0] = cpu_to_be64(ctx->length_aad << 3); lblock.q[1] = cpu_to_be64(ctx->length_input << 3); gcm_ghash_add(gcm, ctx, &lblock); aes_encrypt_block(&lblock, key, &ctx->iv); block128_xor(&ctx->tag, &lblock); for (i = 0; i < 16; i++) { tag[i] = ctx->tag.b[i]; } } void tmd_aes_gcm_full_encrypt(const aes_key *key, const aes_gcm *gcm , const uint8_t *iv, uint32_t ivLen , const uint8_t *aad, uint32_t aadLen , const uint8_t *pt, uint32_t ptLen , uint8_t *ct, uint8_t *tag) { aes_ctx ctx, newCTX; tmd_aes_ctx_init(gcm, &ctx, key, iv, ivLen); tmd_aes_gcm_encrypt(ct, gcm, &ctx, key, pt, ptLen, &newCTX); tmd_aes_gcm_aad(gcm, &newCTX, aad, aadLen); tmd_aes_gcm_finish(tag, gcm, key, &newCTX); } void tmd_aes_gcm_full_decrypt( const aes_key *key, const aes_gcm *gcm , const uint8_t *iv, uint32_t ivLen , const uint8_t *aad, uint32_t aadLen , const uint8_t *ct, uint32_t ctLen , uint8_t *pt, uint8_t *tag) { aes_ctx ctx, newCTX; tmd_aes_ctx_init(gcm, &ctx, key, iv, ivLen); tmd_aes_gcm_decrypt(pt, gcm, &ctx, key, ct, ctLen, &newCTX); tmd_aes_gcm_aad(gcm, &newCTX, aad, aadLen); tmd_aes_gcm_finish(tag, gcm, key, &newCTX); } void tmd_aes_generic_encrypt_ecb(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks) { for ( ; nb_blocks-- > 0; input++, output++) { tmd_aes_generic_encrypt_block(output, key, input); } } void tmd_aes_generic_decrypt_ecb(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks) { for ( ; nb_blocks-- > 0; input++, output++) { tmd_aes_generic_decrypt_block(output, key, input); } } void tmd_aes_generic_encrypt_cbc(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const aes_block *input, uint32_t nb_blocks) { /* preload IV in block */ block128_copy(newIV, iv); for ( ; nb_blocks-- > 0; input++, output++) { block128_xor(newIV, (block128 *) input); tmd_aes_generic_encrypt_block(newIV, key, newIV); block128_copy((block128 *) output, newIV); } } void tmd_aes_generic_decrypt_cbc(aes_block *output, const aes_key *key, const aes_block *ivini, aes_block *newIV, const aes_block *input, uint32_t nb_blocks) { aes_block block, blocko; aes_block *iv; iv = newIV; /* preload IV in block */ block128_copy(iv, ivini); for ( ; nb_blocks-- > 0; input++, output++) { block128_copy(&block, (block128 *) input); tmd_aes_generic_decrypt_block(&blocko, key, &block); block128_vxor((block128 *) output, &blocko, iv); block128_copy(iv, &block); } } void tmd_aes_generic_encrypt_ctr(uint8_t *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const uint8_t *input, uint32_t len) { aes_block block, o; uint32_t nb_blocks = len / 16; int i; /* preload IV in block */ block128_copy(&block, iv); for ( ; nb_blocks-- > 0; block128_inc_be(&block), output += 16, input += 16) { aes_encrypt_block(&o, key, &block); block128_vxor((block128 *) output, &o, (block128 *) input); } if ((len % 16) != 0) { aes_encrypt_block(&o, key, &block); for (i = 0; i < (len % 16); i++) { *output = ((uint8_t *) &o)[i] ^ *input; output++; input++; } } if(NULL != newIV) block128_copy(newIV, &block); } void tmd_aes_generic_encrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks) { aes_block block, tweak; /* load IV and encrypt it using k2 as the tweak */ block128_copy(&tweak, dataunit); aes_encrypt_block(&tweak, k2, &tweak); /* TO OPTIMISE: this is really inefficient way to do that */ while (spoint-- > 0) tmd_gf_mulx(&tweak); for ( ; nb_blocks-- > 0; input++, output++, tmd_gf_mulx(&tweak)) { block128_vxor(&block, input, &tweak); aes_encrypt_block(&block, k1, &block); block128_vxor(output, &block, &tweak); } } void tmd_aes_generic_decrypt_xts(aes_block *output, const aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks) { aes_block block, tweak; /* load IV and encrypt it using k2 as the tweak */ block128_copy(&tweak, dataunit); aes_encrypt_block(&tweak, k2, &tweak); /* TO OPTIMISE: this is really inefficient way to do that */ while (spoint-- > 0) tmd_gf_mulx(&tweak); for ( ; nb_blocks-- > 0; input++, output++, tmd_gf_mulx(&tweak)) { block128_vxor(&block, input, &tweak); aes_decrypt_block(&block, k1, &block); block128_vxor(output, &block, &tweak); } } void tmd_aes_generic_gcm_encrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX) { aes_block out; memcpy(newCTX, ctx, sizeof(aes_ctx)); newCTX->length_input += length; for (; length >= 16; input += 16, output += 16, length -= 16) { block128_inc_be(&newCTX->civ); aes_encrypt_block(&out, key, &newCTX->civ); block128_xor(&out, (block128 *) input); gcm_ghash_add(gcm, newCTX, &out); block128_copy((block128 *) output, &out); } if (length > 0) { aes_block tmp; int i; block128_inc_be(&newCTX->civ); /* create e(civ) in out */ aes_encrypt_block(&out, key, &newCTX->civ); /* initialize a tmp as input and xor it to e(civ) */ block128_zero(&tmp); block128_copy_bytes(&tmp, input, length); block128_xor_bytes(&tmp, out.b, length); gcm_ghash_add(gcm, newCTX, &tmp); for (i = 0; i < length; i++) { output[i] = tmp.b[i]; } } } void tmd_aes_generic_gcm_decrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX) { aes_block out; memcpy(newCTX, ctx, sizeof(aes_ctx)); newCTX->length_input += length; for (; length >= 16; input += 16, output += 16, length -= 16) { block128_inc_be(&newCTX->civ); aes_encrypt_block(&out, key, &newCTX->civ); gcm_ghash_add(gcm, newCTX, (block128 *) input); block128_xor(&out, (block128 *) input); block128_copy((block128 *) output, &out); } if (length > 0) { aes_block tmp; int i; block128_inc_be(&newCTX->civ); block128_zero(&tmp); block128_copy_bytes(&tmp, input, length); gcm_ghash_add(gcm, newCTX, &tmp); aes_encrypt_block(&out, key, &newCTX->civ); block128_xor_bytes(&tmp, out.b, length); for (i = 0; i < length; i++) { output[i] = tmp.b[i]; } } } cipher-aes128-0.7.0.3/cbits/aes.h0000644000000000000000000001155712761471030014357 0ustar0000000000000000/* * Copyright (C) 2008 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * AES implementation */ #ifndef AES_H #define AES_H #include #include "block128.h" typedef block128 aes_block; /* size = 456 */ typedef struct { uint8_t nbr; /* number of rounds: 10 (128), 12 (192), 14 (256) */ uint8_t strength; /* 128 = 0, 192 = 1, 256 = 2 */ uint8_t _padding[6]; uint8_t data[16*14*2]; } aes_key; /* size = 4*16+2*8= 80 */ typedef struct { aes_block h; } aes_gcm; typedef struct { aes_block tag; aes_block iv; aes_block civ; uint64_t length_aad; uint64_t length_input; } aes_ctx; aes_key *tmd_allocatekey(); aes_ctx *tmd_allocatectx(); aes_gcm *tmd_allocategcm(); void tmd_freekey(aes_key *k); void tmd_freectx(aes_ctx *c); void tmd_freegcm(aes_gcm *g); /* in bytes: either 16,24,32 */ void tmd_aes_initkey(aes_key *ctx, uint8_t *key, uint8_t size); void tmd_aes_encrypt(aes_block *output, const aes_key *key, const aes_block *input); void tmd_aes_decrypt(aes_block *output, const aes_key *key, const aes_block *input); void tmd_aes_encrypt_ecb(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks); void tmd_aes_decrypt_ecb(aes_block *output, const aes_key *key, const aes_block *input, uint32_t nb_blocks); void tmd_aes_encrypt_cbc(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *niv, const aes_block *input, uint32_t nb_blocks); void tmd_aes_decrypt_cbc(aes_block *output, const aes_key *key, const aes_block *iv, aes_block *niv, const aes_block *input, uint32_t nb_blocks); void tmd_aes_encrypt_ctr(uint8_t *output, const aes_key *key, const aes_block *iv, aes_block *newIV, const uint8_t *input, uint32_t len); void tmd_aes_gen_ctr(aes_block *output, const aes_key *key, aes_block *iv, uint32_t nb_blocks); void tmd_aes_encrypt_xts(aes_block *output, const aes_key *key, aes_key *key2, aes_block *sector, uint32_t spoint, aes_block *input, uint32_t nb_blocks); void tmd_aes_decrypt_xts(aes_block *output, const aes_key *key, aes_key *key2, aes_block *sector, uint32_t spoint, aes_block *input, uint32_t nb_blocks); void tmd_aes_gcm_init(aes_gcm *gcm, const aes_key *key); void tmd_aes_ctx_init(const aes_gcm *gcm, aes_ctx *ctx, const aes_key *key, const uint8_t *iv, uint32_t len); void tmd_aes_gcm_aad(const aes_gcm *gcm, aes_ctx *ctx, const uint8_t *input, uint32_t length); void tmd_aes_gcm_encrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX); void tmd_aes_gcm_decrypt(uint8_t *output, const aes_gcm *gcm, const aes_ctx *ctx, const aes_key *key, const uint8_t *input, uint32_t length, aes_ctx *newCTX); void tmd_aes_gcm_finish(uint8_t *tag, const aes_gcm *gcm, const aes_key *key, aes_ctx *ctx); void tmd_aes_gcm_full_encrypt( const aes_key *key, const aes_gcm *gcm , const uint8_t *iv, uint32_t ivLen , const uint8_t *aad, uint32_t aadLen , const uint8_t *pt, uint32_t ptLen , uint8_t *ct, uint8_t *tag); void tmd_aes_gcm_full_decrypt( const aes_key *key, const aes_gcm *gcm , const uint8_t *iv, uint32_t ivLen , const uint8_t *aad, uint32_t aadLen , const uint8_t *ct, uint32_t ctLen , uint8_t *pt, uint8_t *tag); #endif cipher-aes128-0.7.0.3/cbits/aes_generic.c0000644000000000000000000005013712761471030016043 0ustar0000000000000000/* * Copyright (C) 2008 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * AES implementation */ #include #include #include "aes.h" #include "bitfn.h" static uint8_t sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; static uint8_t rsbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; static uint8_t Rcon[] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, }; #define G(a,b,c,d,e,f) { a,b,c,d,e,f } static uint8_t gmtab[256][6] = { G(0x00, 0x00, 0x00, 0x00, 0x00, 0x00), G(0x02, 0x03, 0x09, 0x0b, 0x0d, 0x0e), G(0x04, 0x06, 0x12, 0x16, 0x1a, 0x1c), G(0x06, 0x05, 0x1b, 0x1d, 0x17, 0x12), G(0x08, 0x0c, 0x24, 0x2c, 0x34, 0x38), G(0x0a, 0x0f, 0x2d, 0x27, 0x39, 0x36), G(0x0c, 0x0a, 0x36, 0x3a, 0x2e, 0x24), G(0x0e, 0x09, 0x3f, 0x31, 0x23, 0x2a), G(0x10, 0x18, 0x48, 0x58, 0x68, 0x70), G(0x12, 0x1b, 0x41, 0x53, 0x65, 0x7e), G(0x14, 0x1e, 0x5a, 0x4e, 0x72, 0x6c), G(0x16, 0x1d, 0x53, 0x45, 0x7f, 0x62), G(0x18, 0x14, 0x6c, 0x74, 0x5c, 0x48), G(0x1a, 0x17, 0x65, 0x7f, 0x51, 0x46), G(0x1c, 0x12, 0x7e, 0x62, 0x46, 0x54), G(0x1e, 0x11, 0x77, 0x69, 0x4b, 0x5a), G(0x20, 0x30, 0x90, 0xb0, 0xd0, 0xe0), G(0x22, 0x33, 0x99, 0xbb, 0xdd, 0xee), G(0x24, 0x36, 0x82, 0xa6, 0xca, 0xfc), G(0x26, 0x35, 0x8b, 0xad, 0xc7, 0xf2), G(0x28, 0x3c, 0xb4, 0x9c, 0xe4, 0xd8), G(0x2a, 0x3f, 0xbd, 0x97, 0xe9, 0xd6), G(0x2c, 0x3a, 0xa6, 0x8a, 0xfe, 0xc4), G(0x2e, 0x39, 0xaf, 0x81, 0xf3, 0xca), G(0x30, 0x28, 0xd8, 0xe8, 0xb8, 0x90), G(0x32, 0x2b, 0xd1, 0xe3, 0xb5, 0x9e), G(0x34, 0x2e, 0xca, 0xfe, 0xa2, 0x8c), G(0x36, 0x2d, 0xc3, 0xf5, 0xaf, 0x82), G(0x38, 0x24, 0xfc, 0xc4, 0x8c, 0xa8), G(0x3a, 0x27, 0xf5, 0xcf, 0x81, 0xa6), G(0x3c, 0x22, 0xee, 0xd2, 0x96, 0xb4), G(0x3e, 0x21, 0xe7, 0xd9, 0x9b, 0xba), G(0x40, 0x60, 0x3b, 0x7b, 0xbb, 0xdb), G(0x42, 0x63, 0x32, 0x70, 0xb6, 0xd5), G(0x44, 0x66, 0x29, 0x6d, 0xa1, 0xc7), G(0x46, 0x65, 0x20, 0x66, 0xac, 0xc9), G(0x48, 0x6c, 0x1f, 0x57, 0x8f, 0xe3), G(0x4a, 0x6f, 0x16, 0x5c, 0x82, 0xed), G(0x4c, 0x6a, 0x0d, 0x41, 0x95, 0xff), G(0x4e, 0x69, 0x04, 0x4a, 0x98, 0xf1), G(0x50, 0x78, 0x73, 0x23, 0xd3, 0xab), G(0x52, 0x7b, 0x7a, 0x28, 0xde, 0xa5), G(0x54, 0x7e, 0x61, 0x35, 0xc9, 0xb7), G(0x56, 0x7d, 0x68, 0x3e, 0xc4, 0xb9), G(0x58, 0x74, 0x57, 0x0f, 0xe7, 0x93), G(0x5a, 0x77, 0x5e, 0x04, 0xea, 0x9d), G(0x5c, 0x72, 0x45, 0x19, 0xfd, 0x8f), G(0x5e, 0x71, 0x4c, 0x12, 0xf0, 0x81), G(0x60, 0x50, 0xab, 0xcb, 0x6b, 0x3b), G(0x62, 0x53, 0xa2, 0xc0, 0x66, 0x35), G(0x64, 0x56, 0xb9, 0xdd, 0x71, 0x27), G(0x66, 0x55, 0xb0, 0xd6, 0x7c, 0x29), G(0x68, 0x5c, 0x8f, 0xe7, 0x5f, 0x03), G(0x6a, 0x5f, 0x86, 0xec, 0x52, 0x0d), G(0x6c, 0x5a, 0x9d, 0xf1, 0x45, 0x1f), G(0x6e, 0x59, 0x94, 0xfa, 0x48, 0x11), G(0x70, 0x48, 0xe3, 0x93, 0x03, 0x4b), G(0x72, 0x4b, 0xea, 0x98, 0x0e, 0x45), G(0x74, 0x4e, 0xf1, 0x85, 0x19, 0x57), G(0x76, 0x4d, 0xf8, 0x8e, 0x14, 0x59), G(0x78, 0x44, 0xc7, 0xbf, 0x37, 0x73), G(0x7a, 0x47, 0xce, 0xb4, 0x3a, 0x7d), G(0x7c, 0x42, 0xd5, 0xa9, 0x2d, 0x6f), G(0x7e, 0x41, 0xdc, 0xa2, 0x20, 0x61), G(0x80, 0xc0, 0x76, 0xf6, 0x6d, 0xad), G(0x82, 0xc3, 0x7f, 0xfd, 0x60, 0xa3), G(0x84, 0xc6, 0x64, 0xe0, 0x77, 0xb1), G(0x86, 0xc5, 0x6d, 0xeb, 0x7a, 0xbf), G(0x88, 0xcc, 0x52, 0xda, 0x59, 0x95), G(0x8a, 0xcf, 0x5b, 0xd1, 0x54, 0x9b), G(0x8c, 0xca, 0x40, 0xcc, 0x43, 0x89), G(0x8e, 0xc9, 0x49, 0xc7, 0x4e, 0x87), G(0x90, 0xd8, 0x3e, 0xae, 0x05, 0xdd), G(0x92, 0xdb, 0x37, 0xa5, 0x08, 0xd3), G(0x94, 0xde, 0x2c, 0xb8, 0x1f, 0xc1), G(0x96, 0xdd, 0x25, 0xb3, 0x12, 0xcf), G(0x98, 0xd4, 0x1a, 0x82, 0x31, 0xe5), G(0x9a, 0xd7, 0x13, 0x89, 0x3c, 0xeb), G(0x9c, 0xd2, 0x08, 0x94, 0x2b, 0xf9), G(0x9e, 0xd1, 0x01, 0x9f, 0x26, 0xf7), G(0xa0, 0xf0, 0xe6, 0x46, 0xbd, 0x4d), G(0xa2, 0xf3, 0xef, 0x4d, 0xb0, 0x43), G(0xa4, 0xf6, 0xf4, 0x50, 0xa7, 0x51), G(0xa6, 0xf5, 0xfd, 0x5b, 0xaa, 0x5f), G(0xa8, 0xfc, 0xc2, 0x6a, 0x89, 0x75), G(0xaa, 0xff, 0xcb, 0x61, 0x84, 0x7b), G(0xac, 0xfa, 0xd0, 0x7c, 0x93, 0x69), G(0xae, 0xf9, 0xd9, 0x77, 0x9e, 0x67), G(0xb0, 0xe8, 0xae, 0x1e, 0xd5, 0x3d), G(0xb2, 0xeb, 0xa7, 0x15, 0xd8, 0x33), G(0xb4, 0xee, 0xbc, 0x08, 0xcf, 0x21), G(0xb6, 0xed, 0xb5, 0x03, 0xc2, 0x2f), G(0xb8, 0xe4, 0x8a, 0x32, 0xe1, 0x05), G(0xba, 0xe7, 0x83, 0x39, 0xec, 0x0b), G(0xbc, 0xe2, 0x98, 0x24, 0xfb, 0x19), G(0xbe, 0xe1, 0x91, 0x2f, 0xf6, 0x17), G(0xc0, 0xa0, 0x4d, 0x8d, 0xd6, 0x76), G(0xc2, 0xa3, 0x44, 0x86, 0xdb, 0x78), G(0xc4, 0xa6, 0x5f, 0x9b, 0xcc, 0x6a), G(0xc6, 0xa5, 0x56, 0x90, 0xc1, 0x64), G(0xc8, 0xac, 0x69, 0xa1, 0xe2, 0x4e), G(0xca, 0xaf, 0x60, 0xaa, 0xef, 0x40), G(0xcc, 0xaa, 0x7b, 0xb7, 0xf8, 0x52), G(0xce, 0xa9, 0x72, 0xbc, 0xf5, 0x5c), G(0xd0, 0xb8, 0x05, 0xd5, 0xbe, 0x06), G(0xd2, 0xbb, 0x0c, 0xde, 0xb3, 0x08), G(0xd4, 0xbe, 0x17, 0xc3, 0xa4, 0x1a), G(0xd6, 0xbd, 0x1e, 0xc8, 0xa9, 0x14), G(0xd8, 0xb4, 0x21, 0xf9, 0x8a, 0x3e), G(0xda, 0xb7, 0x28, 0xf2, 0x87, 0x30), G(0xdc, 0xb2, 0x33, 0xef, 0x90, 0x22), G(0xde, 0xb1, 0x3a, 0xe4, 0x9d, 0x2c), G(0xe0, 0x90, 0xdd, 0x3d, 0x06, 0x96), G(0xe2, 0x93, 0xd4, 0x36, 0x0b, 0x98), G(0xe4, 0x96, 0xcf, 0x2b, 0x1c, 0x8a), G(0xe6, 0x95, 0xc6, 0x20, 0x11, 0x84), G(0xe8, 0x9c, 0xf9, 0x11, 0x32, 0xae), G(0xea, 0x9f, 0xf0, 0x1a, 0x3f, 0xa0), G(0xec, 0x9a, 0xeb, 0x07, 0x28, 0xb2), G(0xee, 0x99, 0xe2, 0x0c, 0x25, 0xbc), G(0xf0, 0x88, 0x95, 0x65, 0x6e, 0xe6), G(0xf2, 0x8b, 0x9c, 0x6e, 0x63, 0xe8), G(0xf4, 0x8e, 0x87, 0x73, 0x74, 0xfa), G(0xf6, 0x8d, 0x8e, 0x78, 0x79, 0xf4), G(0xf8, 0x84, 0xb1, 0x49, 0x5a, 0xde), G(0xfa, 0x87, 0xb8, 0x42, 0x57, 0xd0), G(0xfc, 0x82, 0xa3, 0x5f, 0x40, 0xc2), G(0xfe, 0x81, 0xaa, 0x54, 0x4d, 0xcc), G(0x1b, 0x9b, 0xec, 0xf7, 0xda, 0x41), G(0x19, 0x98, 0xe5, 0xfc, 0xd7, 0x4f), G(0x1f, 0x9d, 0xfe, 0xe1, 0xc0, 0x5d), G(0x1d, 0x9e, 0xf7, 0xea, 0xcd, 0x53), G(0x13, 0x97, 0xc8, 0xdb, 0xee, 0x79), G(0x11, 0x94, 0xc1, 0xd0, 0xe3, 0x77), G(0x17, 0x91, 0xda, 0xcd, 0xf4, 0x65), G(0x15, 0x92, 0xd3, 0xc6, 0xf9, 0x6b), G(0x0b, 0x83, 0xa4, 0xaf, 0xb2, 0x31), G(0x09, 0x80, 0xad, 0xa4, 0xbf, 0x3f), G(0x0f, 0x85, 0xb6, 0xb9, 0xa8, 0x2d), G(0x0d, 0x86, 0xbf, 0xb2, 0xa5, 0x23), G(0x03, 0x8f, 0x80, 0x83, 0x86, 0x09), G(0x01, 0x8c, 0x89, 0x88, 0x8b, 0x07), G(0x07, 0x89, 0x92, 0x95, 0x9c, 0x15), G(0x05, 0x8a, 0x9b, 0x9e, 0x91, 0x1b), G(0x3b, 0xab, 0x7c, 0x47, 0x0a, 0xa1), G(0x39, 0xa8, 0x75, 0x4c, 0x07, 0xaf), G(0x3f, 0xad, 0x6e, 0x51, 0x10, 0xbd), G(0x3d, 0xae, 0x67, 0x5a, 0x1d, 0xb3), G(0x33, 0xa7, 0x58, 0x6b, 0x3e, 0x99), G(0x31, 0xa4, 0x51, 0x60, 0x33, 0x97), G(0x37, 0xa1, 0x4a, 0x7d, 0x24, 0x85), G(0x35, 0xa2, 0x43, 0x76, 0x29, 0x8b), G(0x2b, 0xb3, 0x34, 0x1f, 0x62, 0xd1), G(0x29, 0xb0, 0x3d, 0x14, 0x6f, 0xdf), G(0x2f, 0xb5, 0x26, 0x09, 0x78, 0xcd), G(0x2d, 0xb6, 0x2f, 0x02, 0x75, 0xc3), G(0x23, 0xbf, 0x10, 0x33, 0x56, 0xe9), G(0x21, 0xbc, 0x19, 0x38, 0x5b, 0xe7), G(0x27, 0xb9, 0x02, 0x25, 0x4c, 0xf5), G(0x25, 0xba, 0x0b, 0x2e, 0x41, 0xfb), G(0x5b, 0xfb, 0xd7, 0x8c, 0x61, 0x9a), G(0x59, 0xf8, 0xde, 0x87, 0x6c, 0x94), G(0x5f, 0xfd, 0xc5, 0x9a, 0x7b, 0x86), G(0x5d, 0xfe, 0xcc, 0x91, 0x76, 0x88), G(0x53, 0xf7, 0xf3, 0xa0, 0x55, 0xa2), G(0x51, 0xf4, 0xfa, 0xab, 0x58, 0xac), G(0x57, 0xf1, 0xe1, 0xb6, 0x4f, 0xbe), G(0x55, 0xf2, 0xe8, 0xbd, 0x42, 0xb0), G(0x4b, 0xe3, 0x9f, 0xd4, 0x09, 0xea), G(0x49, 0xe0, 0x96, 0xdf, 0x04, 0xe4), G(0x4f, 0xe5, 0x8d, 0xc2, 0x13, 0xf6), G(0x4d, 0xe6, 0x84, 0xc9, 0x1e, 0xf8), G(0x43, 0xef, 0xbb, 0xf8, 0x3d, 0xd2), G(0x41, 0xec, 0xb2, 0xf3, 0x30, 0xdc), G(0x47, 0xe9, 0xa9, 0xee, 0x27, 0xce), G(0x45, 0xea, 0xa0, 0xe5, 0x2a, 0xc0), G(0x7b, 0xcb, 0x47, 0x3c, 0xb1, 0x7a), G(0x79, 0xc8, 0x4e, 0x37, 0xbc, 0x74), G(0x7f, 0xcd, 0x55, 0x2a, 0xab, 0x66), G(0x7d, 0xce, 0x5c, 0x21, 0xa6, 0x68), G(0x73, 0xc7, 0x63, 0x10, 0x85, 0x42), G(0x71, 0xc4, 0x6a, 0x1b, 0x88, 0x4c), G(0x77, 0xc1, 0x71, 0x06, 0x9f, 0x5e), G(0x75, 0xc2, 0x78, 0x0d, 0x92, 0x50), G(0x6b, 0xd3, 0x0f, 0x64, 0xd9, 0x0a), G(0x69, 0xd0, 0x06, 0x6f, 0xd4, 0x04), G(0x6f, 0xd5, 0x1d, 0x72, 0xc3, 0x16), G(0x6d, 0xd6, 0x14, 0x79, 0xce, 0x18), G(0x63, 0xdf, 0x2b, 0x48, 0xed, 0x32), G(0x61, 0xdc, 0x22, 0x43, 0xe0, 0x3c), G(0x67, 0xd9, 0x39, 0x5e, 0xf7, 0x2e), G(0x65, 0xda, 0x30, 0x55, 0xfa, 0x20), G(0x9b, 0x5b, 0x9a, 0x01, 0xb7, 0xec), G(0x99, 0x58, 0x93, 0x0a, 0xba, 0xe2), G(0x9f, 0x5d, 0x88, 0x17, 0xad, 0xf0), G(0x9d, 0x5e, 0x81, 0x1c, 0xa0, 0xfe), G(0x93, 0x57, 0xbe, 0x2d, 0x83, 0xd4), G(0x91, 0x54, 0xb7, 0x26, 0x8e, 0xda), G(0x97, 0x51, 0xac, 0x3b, 0x99, 0xc8), G(0x95, 0x52, 0xa5, 0x30, 0x94, 0xc6), G(0x8b, 0x43, 0xd2, 0x59, 0xdf, 0x9c), G(0x89, 0x40, 0xdb, 0x52, 0xd2, 0x92), G(0x8f, 0x45, 0xc0, 0x4f, 0xc5, 0x80), G(0x8d, 0x46, 0xc9, 0x44, 0xc8, 0x8e), G(0x83, 0x4f, 0xf6, 0x75, 0xeb, 0xa4), G(0x81, 0x4c, 0xff, 0x7e, 0xe6, 0xaa), G(0x87, 0x49, 0xe4, 0x63, 0xf1, 0xb8), G(0x85, 0x4a, 0xed, 0x68, 0xfc, 0xb6), G(0xbb, 0x6b, 0x0a, 0xb1, 0x67, 0x0c), G(0xb9, 0x68, 0x03, 0xba, 0x6a, 0x02), G(0xbf, 0x6d, 0x18, 0xa7, 0x7d, 0x10), G(0xbd, 0x6e, 0x11, 0xac, 0x70, 0x1e), G(0xb3, 0x67, 0x2e, 0x9d, 0x53, 0x34), G(0xb1, 0x64, 0x27, 0x96, 0x5e, 0x3a), G(0xb7, 0x61, 0x3c, 0x8b, 0x49, 0x28), G(0xb5, 0x62, 0x35, 0x80, 0x44, 0x26), G(0xab, 0x73, 0x42, 0xe9, 0x0f, 0x7c), G(0xa9, 0x70, 0x4b, 0xe2, 0x02, 0x72), G(0xaf, 0x75, 0x50, 0xff, 0x15, 0x60), G(0xad, 0x76, 0x59, 0xf4, 0x18, 0x6e), G(0xa3, 0x7f, 0x66, 0xc5, 0x3b, 0x44), G(0xa1, 0x7c, 0x6f, 0xce, 0x36, 0x4a), G(0xa7, 0x79, 0x74, 0xd3, 0x21, 0x58), G(0xa5, 0x7a, 0x7d, 0xd8, 0x2c, 0x56), G(0xdb, 0x3b, 0xa1, 0x7a, 0x0c, 0x37), G(0xd9, 0x38, 0xa8, 0x71, 0x01, 0x39), G(0xdf, 0x3d, 0xb3, 0x6c, 0x16, 0x2b), G(0xdd, 0x3e, 0xba, 0x67, 0x1b, 0x25), G(0xd3, 0x37, 0x85, 0x56, 0x38, 0x0f), G(0xd1, 0x34, 0x8c, 0x5d, 0x35, 0x01), G(0xd7, 0x31, 0x97, 0x40, 0x22, 0x13), G(0xd5, 0x32, 0x9e, 0x4b, 0x2f, 0x1d), G(0xcb, 0x23, 0xe9, 0x22, 0x64, 0x47), G(0xc9, 0x20, 0xe0, 0x29, 0x69, 0x49), G(0xcf, 0x25, 0xfb, 0x34, 0x7e, 0x5b), G(0xcd, 0x26, 0xf2, 0x3f, 0x73, 0x55), G(0xc3, 0x2f, 0xcd, 0x0e, 0x50, 0x7f), G(0xc1, 0x2c, 0xc4, 0x05, 0x5d, 0x71), G(0xc7, 0x29, 0xdf, 0x18, 0x4a, 0x63), G(0xc5, 0x2a, 0xd6, 0x13, 0x47, 0x6d), G(0xfb, 0x0b, 0x31, 0xca, 0xdc, 0xd7), G(0xf9, 0x08, 0x38, 0xc1, 0xd1, 0xd9), G(0xff, 0x0d, 0x23, 0xdc, 0xc6, 0xcb), G(0xfd, 0x0e, 0x2a, 0xd7, 0xcb, 0xc5), G(0xf3, 0x07, 0x15, 0xe6, 0xe8, 0xef), G(0xf1, 0x04, 0x1c, 0xed, 0xe5, 0xe1), G(0xf7, 0x01, 0x07, 0xf0, 0xf2, 0xf3), G(0xf5, 0x02, 0x0e, 0xfb, 0xff, 0xfd), G(0xeb, 0x13, 0x79, 0x92, 0xb4, 0xa7), G(0xe9, 0x10, 0x70, 0x99, 0xb9, 0xa9), G(0xef, 0x15, 0x6b, 0x84, 0xae, 0xbb), G(0xed, 0x16, 0x62, 0x8f, 0xa3, 0xb5), G(0xe3, 0x1f, 0x5d, 0xbe, 0x80, 0x9f), G(0xe1, 0x1c, 0x54, 0xb5, 0x8d, 0x91), G(0xe7, 0x19, 0x4f, 0xa8, 0x9a, 0x83), G(0xe5, 0x1a, 0x46, 0xa3, 0x97, 0x8d), }; #undef G static void expand_key(uint8_t *expandedKey, const uint8_t *key, int size, size_t expandedKeySize) { int csz; int i; uint8_t t[4] = { 0 }; for (i = 0; i < size; i++) expandedKey[i] = key[i]; csz = size; i = 1; while (csz < expandedKeySize) { t[0] = expandedKey[(csz - 4) + 0]; t[1] = expandedKey[(csz - 4) + 1]; t[2] = expandedKey[(csz - 4) + 2]; t[3] = expandedKey[(csz - 4) + 3]; if (csz % size == 0) { uint8_t tmp; tmp = t[0]; t[0] = sbox[t[1]] ^ Rcon[i++ % sizeof(Rcon)]; t[1] = sbox[t[2]]; t[2] = sbox[t[3]]; t[3] = sbox[tmp]; } if (size == 32 && ((csz % size) == 16)) { t[0] = sbox[t[0]]; t[1] = sbox[t[1]]; t[2] = sbox[t[2]]; t[3] = sbox[t[3]]; } expandedKey[csz] = expandedKey[csz - size] ^ t[0]; csz++; expandedKey[csz] = expandedKey[csz - size] ^ t[1]; csz++; expandedKey[csz] = expandedKey[csz - size] ^ t[2]; csz++; expandedKey[csz] = expandedKey[csz - size] ^ t[3]; csz++; } } static void shift_rows(uint8_t *state) { uint32_t *s32; int i; for (i = 0; i < 16; i++) state[i] = sbox[state[i]]; s32 = (uint32_t *) state; s32[1] = rol32_be(s32[1], 8); s32[2] = rol32_be(s32[2], 16); s32[3] = rol32_be(s32[3], 24); } static void add_round_key(uint8_t *state, uint8_t *rk) { uint32_t *s32, *r32; s32 = (uint32_t *) state; r32 = (uint32_t *) rk; s32[0] ^= r32[0]; s32[1] ^= r32[1]; s32[2] ^= r32[2]; s32[3] ^= r32[3]; } #define gm1(a) (a) #define gm2(a) gmtab[a][0] #define gm3(a) gmtab[a][1] #define gm9(a) gmtab[a][2] #define gm11(a) gmtab[a][3] #define gm13(a) gmtab[a][4] #define gm14(a) gmtab[a][5] static void mix_columns(uint8_t *state) { int i; uint8_t cpy[4]; for (i = 0; i < 4; i++) { cpy[0] = state[0 * 4 + i]; cpy[1] = state[1 * 4 + i]; cpy[2] = state[2 * 4 + i]; cpy[3] = state[3 * 4 + i]; state[i] = gm2(cpy[0]) ^ gm1(cpy[3]) ^ gm1(cpy[2]) ^ gm3(cpy[1]); state[4+i] = gm2(cpy[1]) ^ gm1(cpy[0]) ^ gm1(cpy[3]) ^ gm3(cpy[2]); state[8+i] = gm2(cpy[2]) ^ gm1(cpy[1]) ^ gm1(cpy[0]) ^ gm3(cpy[3]); state[12+i] = gm2(cpy[3]) ^ gm1(cpy[2]) ^ gm1(cpy[1]) ^ gm3(cpy[0]); } } static void create_round_key(const uint8_t *expandedKey, uint8_t *rk) { int i,j; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) rk[i + j * 4] = expandedKey[i * 4 + j]; } static void aes_main(const aes_key *key, uint8_t *state) { int i = 0; uint8_t rk[16]; create_round_key(key->data, rk); add_round_key(state, rk); for (i = 1; i < key->nbr; i++) { create_round_key(key->data + 16 * i, rk); shift_rows(state); mix_columns(state); add_round_key(state, rk); } create_round_key(key->data + 16 * key->nbr, rk); shift_rows(state); add_round_key(state, rk); } static void shift_rows_inv(uint8_t *state) { uint32_t *s32; int i; s32 = (uint32_t *) state; s32[1] = ror32_be(s32[1], 8); s32[2] = ror32_be(s32[2], 16); s32[3] = ror32_be(s32[3], 24); for (i = 0; i < 16; i++) state[i] = rsbox[state[i]]; } static void mix_columns_inv(uint8_t *state) { int i; uint8_t cpy[4]; for (i = 0; i < 4; i++) { cpy[0] = state[0 * 4 + i]; cpy[1] = state[1 * 4 + i]; cpy[2] = state[2 * 4 + i]; cpy[3] = state[3 * 4 + i]; state[i] = gm14(cpy[0]) ^ gm9(cpy[3]) ^ gm13(cpy[2]) ^ gm11(cpy[1]); state[4+i] = gm14(cpy[1]) ^ gm9(cpy[0]) ^ gm13(cpy[3]) ^ gm11(cpy[2]); state[8+i] = gm14(cpy[2]) ^ gm9(cpy[1]) ^ gm13(cpy[0]) ^ gm11(cpy[3]); state[12+i] = gm14(cpy[3]) ^ gm9(cpy[2]) ^ gm13(cpy[1]) ^ gm11(cpy[0]); } } static void aes_main_inv(const aes_key *key, uint8_t *state) { int i = 0; uint8_t rk[16]; create_round_key(key->data + 16 * key->nbr, rk); add_round_key(state, rk); for (i = key->nbr - 1; i > 0; i--) { create_round_key(key->data + 16 * i, rk); shift_rows_inv(state); add_round_key(state, rk); mix_columns_inv(state); } create_round_key(key->data, rk); shift_rows_inv(state); add_round_key(state, rk); } /* Set the block values, for the block: * a0,0 a0,1 a0,2 a0,3 * a1,0 a1,1 a1,2 a1,3 -> a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 * a2,0 a2,1 a2,2 a2,3 * a3,0 a3,1 a3,2 a3,3 */ #define swap_block(t, f) \ t[0] = f[0]; t[4] = f[1]; t[8] = f[2]; t[12] = f[3]; \ t[1] = f[4]; t[5] = f[5]; t[9] = f[6]; t[13] = f[7]; \ t[2] = f[8]; t[6] = f[9]; t[10] = f[10]; t[14] = f[11]; \ t[3] = f[12]; t[7] = f[13]; t[11] = f[14]; t[15] = f[15] void tmd_aes_generic_encrypt_block(aes_block *output, const aes_key *key, const aes_block *input) { uint8_t block[16]; uint8_t *iptr, *optr; iptr = (uint8_t *) input; optr = (uint8_t *) output; swap_block(block, iptr); aes_main(key, block); swap_block(optr, block); } void tmd_aes_generic_decrypt_block(aes_block *output, const aes_key *key, const aes_block *input) { uint8_t block[16]; uint8_t *iptr, *optr; iptr = (uint8_t *) input; optr = (uint8_t *) output; swap_block(block, iptr); aes_main_inv(key, block); swap_block(optr, block); } void tmd_aes_generic_init(aes_key *key, const uint8_t *origkey, uint8_t size) { int esz; switch (size) { case 16: key->nbr = 10; esz = 176; break; case 24: key->nbr = 12; esz = 208; break; case 32: key->nbr = 14; esz = 240; break; default: return; } expand_key(key->data, origkey, size, esz); return; } cipher-aes128-0.7.0.3/cbits/aes_generic.h0000644000000000000000000000352012761471030016042 0ustar0000000000000000/* * Copyright (c) 2012 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "aes.h" void tmd_aes_generic_encrypt_block(aes_block *output, const aes_key *key, const aes_block *input); void tmd_aes_generic_decrypt_block(aes_block *output, const aes_key *key, const aes_block *input); void tmd_aes_generic_init(aes_key *key, const uint8_t *origkey, uint8_t size); cipher-aes128-0.7.0.3/cbits/aes_x86ni.c0000644000000000000000000002574512761471030015412 0ustar0000000000000000/* * Copyright (c) 2012-2013 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef WITH_AESNI #include #include #include #include "aes.h" #include "aes_x86ni.h" #include "block128.h" #include "cpu.h" #ifdef ARCH_X86 #define ALIGN_UP(addr, size) (((addr) + ((size) - 1)) & (~((size) - 1))) #define ALIGNMENT(n) __attribute__((aligned(n))) /* old GCC version doesn't cope with the shuffle parameters, that can take 2 values (0xff and 0xaa) * in our case, passed as argument despite being a immediate 8 bits constant anyway. * un-factorise aes_128_key_expansion into 2 version that have the shuffle parameter explicitly set */ static __m128i aes_128_key_expansion_ff(__m128i key, __m128i keygened) { keygened = _mm_shuffle_epi32(keygened, 0xff); key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); return _mm_xor_si128(key, keygened); } static __m128i aes_128_key_expansion_aa(__m128i key, __m128i keygened) { keygened = _mm_shuffle_epi32(keygened, 0xaa); key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); return _mm_xor_si128(key, keygened); } void tmd_aes_ni_init(aes_key *key, const uint8_t *ikey, uint8_t size) { __m128i k[28]; uint64_t *out = (uint64_t *) key->data; int i; switch (size) { case 16: k[0] = _mm_loadu_si128((const __m128i*) ikey); #define AES_128_key_exp(K, RCON) aes_128_key_expansion_ff(K, _mm_aeskeygenassist_si128(K, RCON)) k[1] = AES_128_key_exp(k[0], 0x01); k[2] = AES_128_key_exp(k[1], 0x02); k[3] = AES_128_key_exp(k[2], 0x04); k[4] = AES_128_key_exp(k[3], 0x08); k[5] = AES_128_key_exp(k[4], 0x10); k[6] = AES_128_key_exp(k[5], 0x20); k[7] = AES_128_key_exp(k[6], 0x40); k[8] = AES_128_key_exp(k[7], 0x80); k[9] = AES_128_key_exp(k[8], 0x1B); k[10] = AES_128_key_exp(k[9], 0x36); /* generate decryption keys in reverse order. * k[10] is shared by last encryption and first decryption rounds * k[20] is shared by first encryption round (and is the original user key) */ k[11] = _mm_aesimc_si128(k[9]); k[12] = _mm_aesimc_si128(k[8]); k[13] = _mm_aesimc_si128(k[7]); k[14] = _mm_aesimc_si128(k[6]); k[15] = _mm_aesimc_si128(k[5]); k[16] = _mm_aesimc_si128(k[4]); k[17] = _mm_aesimc_si128(k[3]); k[18] = _mm_aesimc_si128(k[2]); k[19] = _mm_aesimc_si128(k[1]); for (i = 0; i < 20; i++) _mm_storeu_si128(((__m128i *) out) + i, k[i]); break; case 32: #define AES_256_key_exp_1(K1, K2, RCON) aes_128_key_expansion_ff(K1, _mm_aeskeygenassist_si128(K2, RCON)) #define AES_256_key_exp_2(K1, K2) aes_128_key_expansion_aa(K1, _mm_aeskeygenassist_si128(K2, 0x00)) k[0] = _mm_loadu_si128((const __m128i*) ikey); k[1] = _mm_loadu_si128((const __m128i*) (ikey+16)); k[2] = AES_256_key_exp_1(k[0], k[1], 0x01); k[3] = AES_256_key_exp_2(k[1], k[2]); k[4] = AES_256_key_exp_1(k[2], k[3], 0x02); k[5] = AES_256_key_exp_2(k[3], k[4]); k[6] = AES_256_key_exp_1(k[4], k[5], 0x04); k[7] = AES_256_key_exp_2(k[5], k[6]); k[8] = AES_256_key_exp_1(k[6], k[7], 0x08); k[9] = AES_256_key_exp_2(k[7], k[8]); k[10] = AES_256_key_exp_1(k[8], k[9], 0x10); k[11] = AES_256_key_exp_2(k[9], k[10]); k[12] = AES_256_key_exp_1(k[10], k[11], 0x20); k[13] = AES_256_key_exp_2(k[11], k[12]); k[14] = AES_256_key_exp_1(k[12], k[13], 0x40); k[15] = _mm_aesimc_si128(k[13]); k[16] = _mm_aesimc_si128(k[12]); k[17] = _mm_aesimc_si128(k[11]); k[18] = _mm_aesimc_si128(k[10]); k[19] = _mm_aesimc_si128(k[9]); k[20] = _mm_aesimc_si128(k[8]); k[21] = _mm_aesimc_si128(k[7]); k[22] = _mm_aesimc_si128(k[6]); k[23] = _mm_aesimc_si128(k[5]); k[24] = _mm_aesimc_si128(k[4]); k[25] = _mm_aesimc_si128(k[3]); k[26] = _mm_aesimc_si128(k[2]); k[27] = _mm_aesimc_si128(k[1]); for (i = 0; i < 28; i++) _mm_storeu_si128(((__m128i *) out) + i, k[i]); break; default: break; } } /* TO OPTIMISE: use pcmulqdq... or some faster code. * this is the lamest way of doing it, but i'm out of time. * this is basically a copy of tmd_gf_mulx in gf.c */ static __m128i gfmulx(__m128i v) { uint64_t v_[2] ALIGNMENT(16); const uint64_t gf_mask = 0x8000000000000000; _mm_store_si128((__m128i *) v_, v); uint64_t r = ((v_[1] & gf_mask) ? 0x87 : 0); v_[1] = (v_[1] << 1) | (v_[0] & gf_mask ? 1 : 0); v_[0] = (v_[0] << 1) ^ r; v = _mm_load_si128((__m128i *) v_); return v; } static void unopt_gf_mul(block128 *a, block128 *b) { uint64_t a0, a1, v0, v1; int i, j; a0 = a1 = 0; v0 = cpu_to_be64(a->q[0]); v1 = cpu_to_be64(a->q[1]); for (i = 0; i < 16; i++) for (j = 0x80; j != 0; j >>= 1) { uint8_t x = b->b[i] & j; a0 ^= x ? v0 : 0; a1 ^= x ? v1 : 0; x = (uint8_t) v1 & 1; v1 = (v1 >> 1) | (v0 << 63); v0 = (v0 >> 1) ^ (x ? (0xe1ULL << 56) : 0); } a->q[0] = cpu_to_be64(a0); a->q[1] = cpu_to_be64(a1); } static __m128i ghash_add(__m128i tag, __m128i h, __m128i m) { aes_block _t, _h; tag = _mm_xor_si128(tag, m); _mm_store_si128((__m128i *) &_t, tag); _mm_store_si128((__m128i *) &_h, h); unopt_gf_mul(&_t, &_h); tag = _mm_load_si128((__m128i *) &_t); return tag; } #define PRELOAD_ENC_KEYS128(k) \ __m128i K0 = _mm_loadu_si128(((__m128i *) k)+0); \ __m128i K1 = _mm_loadu_si128(((__m128i *) k)+1); \ __m128i K2 = _mm_loadu_si128(((__m128i *) k)+2); \ __m128i K3 = _mm_loadu_si128(((__m128i *) k)+3); \ __m128i K4 = _mm_loadu_si128(((__m128i *) k)+4); \ __m128i K5 = _mm_loadu_si128(((__m128i *) k)+5); \ __m128i K6 = _mm_loadu_si128(((__m128i *) k)+6); \ __m128i K7 = _mm_loadu_si128(((__m128i *) k)+7); \ __m128i K8 = _mm_loadu_si128(((__m128i *) k)+8); \ __m128i K9 = _mm_loadu_si128(((__m128i *) k)+9); \ __m128i K10 = _mm_loadu_si128(((__m128i *) k)+10); #define PRELOAD_ENC_KEYS256(k) \ PRELOAD_ENC_KEYS128(k) \ __m128i K11 = _mm_loadu_si128(((__m128i *) k)+11); \ __m128i K12 = _mm_loadu_si128(((__m128i *) k)+12); \ __m128i K13 = _mm_loadu_si128(((__m128i *) k)+13); \ __m128i K14 = _mm_loadu_si128(((__m128i *) k)+14); #define DO_ENC_BLOCK128(m) \ m = _mm_xor_si128(m, K0); \ m = _mm_aesenc_si128(m, K1); \ m = _mm_aesenc_si128(m, K2); \ m = _mm_aesenc_si128(m, K3); \ m = _mm_aesenc_si128(m, K4); \ m = _mm_aesenc_si128(m, K5); \ m = _mm_aesenc_si128(m, K6); \ m = _mm_aesenc_si128(m, K7); \ m = _mm_aesenc_si128(m, K8); \ m = _mm_aesenc_si128(m, K9); \ m = _mm_aesenclast_si128(m, K10); #define DO_ENC_BLOCK256(m) \ m = _mm_xor_si128(m, K0); \ m = _mm_aesenc_si128(m, K1); \ m = _mm_aesenc_si128(m, K2); \ m = _mm_aesenc_si128(m, K3); \ m = _mm_aesenc_si128(m, K4); \ m = _mm_aesenc_si128(m, K5); \ m = _mm_aesenc_si128(m, K6); \ m = _mm_aesenc_si128(m, K7); \ m = _mm_aesenc_si128(m, K8); \ m = _mm_aesenc_si128(m, K9); \ m = _mm_aesenc_si128(m, K10); \ m = _mm_aesenc_si128(m, K11); \ m = _mm_aesenc_si128(m, K12); \ m = _mm_aesenc_si128(m, K13); \ m = _mm_aesenclast_si128(m, K14); /* load K0 at K9 from index 'at' */ #define PRELOAD_DEC_KEYS_AT(k, at) \ __m128i K0 = _mm_loadu_si128(((__m128i *) k)+at+0); \ __m128i K1 = _mm_loadu_si128(((__m128i *) k)+at+1); \ __m128i K2 = _mm_loadu_si128(((__m128i *) k)+at+2); \ __m128i K3 = _mm_loadu_si128(((__m128i *) k)+at+3); \ __m128i K4 = _mm_loadu_si128(((__m128i *) k)+at+4); \ __m128i K5 = _mm_loadu_si128(((__m128i *) k)+at+5); \ __m128i K6 = _mm_loadu_si128(((__m128i *) k)+at+6); \ __m128i K7 = _mm_loadu_si128(((__m128i *) k)+at+7); \ __m128i K8 = _mm_loadu_si128(((__m128i *) k)+at+8); \ __m128i K9 = _mm_loadu_si128(((__m128i *) k)+at+9); \ #define PRELOAD_DEC_KEYS128(k) \ PRELOAD_DEC_KEYS_AT(k, 10) \ __m128i K10 = _mm_loadu_si128(((__m128i *) k)+0); #define PRELOAD_DEC_KEYS256(k) \ PRELOAD_DEC_KEYS_AT(k, 14) \ __m128i K10 = _mm_loadu_si128(((__m128i *) k)+14+10); \ __m128i K11 = _mm_loadu_si128(((__m128i *) k)+14+11); \ __m128i K12 = _mm_loadu_si128(((__m128i *) k)+14+12); \ __m128i K13 = _mm_loadu_si128(((__m128i *) k)+14+13); \ __m128i K14 = _mm_loadu_si128(((__m128i *) k)+0); #define DO_DEC_BLOCK128(m) \ m = _mm_xor_si128(m, K0); \ m = _mm_aesdec_si128(m, K1); \ m = _mm_aesdec_si128(m, K2); \ m = _mm_aesdec_si128(m, K3); \ m = _mm_aesdec_si128(m, K4); \ m = _mm_aesdec_si128(m, K5); \ m = _mm_aesdec_si128(m, K6); \ m = _mm_aesdec_si128(m, K7); \ m = _mm_aesdec_si128(m, K8); \ m = _mm_aesdec_si128(m, K9); \ m = _mm_aesdeclast_si128(m, K10); #define DO_DEC_BLOCK256(m) \ m = _mm_xor_si128(m, K0); \ m = _mm_aesdec_si128(m, K1); \ m = _mm_aesdec_si128(m, K2); \ m = _mm_aesdec_si128(m, K3); \ m = _mm_aesdec_si128(m, K4); \ m = _mm_aesdec_si128(m, K5); \ m = _mm_aesdec_si128(m, K6); \ m = _mm_aesdec_si128(m, K7); \ m = _mm_aesdec_si128(m, K8); \ m = _mm_aesdec_si128(m, K9); \ m = _mm_aesdec_si128(m, K10); \ m = _mm_aesdec_si128(m, K11); \ m = _mm_aesdec_si128(m, K12); \ m = _mm_aesdec_si128(m, K13); \ m = _mm_aesdeclast_si128(m, K14); #define SIZE 128 #define SIZED(m) m##128 #define PRELOAD_ENC PRELOAD_ENC_KEYS128 #define DO_ENC_BLOCK DO_ENC_BLOCK128 #define PRELOAD_DEC PRELOAD_DEC_KEYS128 #define DO_DEC_BLOCK DO_DEC_BLOCK128 #include "aes_x86ni_impl.c" #undef SIZE #undef SIZED #undef PRELOAD_ENC #undef PRELOAD_DEC #undef DO_ENC_BLOCK #undef DO_DEC_BLOCK #define SIZED(m) m##256 #define SIZE 256 #define PRELOAD_ENC PRELOAD_ENC_KEYS256 #define DO_ENC_BLOCK DO_ENC_BLOCK256 #define PRELOAD_DEC PRELOAD_DEC_KEYS256 #define DO_DEC_BLOCK DO_DEC_BLOCK256 #include "aes_x86ni_impl.c" #undef SIZE #undef SIZED #undef PRELOAD_ENC #undef PRELOAD_DEC #undef DO_ENC_BLOCK #undef DO_DEC_BLOCK #endif #endif cipher-aes128-0.7.0.3/cbits/aes_x86ni.h0000644000000000000000000000776512761471030015421 0ustar0000000000000000/* * Copyright (c) 2012 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef AES_X86NI_H #define AES_X86NI_H #ifdef WITH_AESNI #if defined(__i386__) || defined(__x86_64__) #include #include #include "aes.h" #include "block128.h" #ifdef IMPL_DEBUG static void block128_sse_print(__m128i m) { block128 b; _mm_storeu_si128((__m128i *) &b.b, m); block128_print(&b); } #endif void tmd_aes_ni_init(aes_key *key, const uint8_t *origkey, uint8_t size); void tmd_aes_ni_encrypt_block128(aes_block *out, aes_key *key, aes_block *in); void tmd_aes_ni_encrypt_block256(aes_block *out, aes_key *key, aes_block *in); void tmd_aes_ni_decrypt_block128(aes_block *out, aes_key *key, aes_block *in); void tmd_aes_ni_decrypt_block256(aes_block *out, aes_key *key, aes_block *in); void tmd_aes_ni_encrypt_ecb128(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks); void tmd_aes_ni_encrypt_ecb256(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks); void tmd_aes_ni_decrypt_ecb128(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks); void tmd_aes_ni_decrypt_ecb256(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks); void tmd_aes_ni_encrypt_cbc128(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks); void tmd_aes_ni_encrypt_cbc256(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks); void tmd_aes_ni_decrypt_cbc128(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks); void tmd_aes_ni_decrypt_cbc256(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks); void tmd_aes_ni_encrypt_ctr128(uint8_t *out, aes_key *key, aes_block *_iv, aes_block *niv, uint8_t *in, uint32_t length); void tmd_aes_ni_encrypt_ctr256(uint8_t *out, aes_key *key, aes_block *_iv, aes_block *niv, uint8_t *in, uint32_t length); void tmd_aes_ni_encrypt_xts128(aes_block *out, aes_key *key1, aes_key *key2, aes_block *_tweak, uint32_t spoint, aes_block *in, uint32_t blocks); void tmd_aes_ni_encrypt_xts256(aes_block *out, aes_key *key1, aes_key *key2, aes_block *_tweak, uint32_t spoint, aes_block *in, uint32_t blocks); void tmd_aes_ni_gcm_encrypt128(uint8_t *out, aes_gcm *gcm, aes_ctx *ctx, aes_key *key, uint8_t *in, uint32_t length, aes_ctx *newCTX); void tmd_aes_ni_gcm_encrypt256(uint8_t *out, aes_gcm *gcm, aes_ctx *ctx, aes_key *key, uint8_t *in, uint32_t length, aes_ctx *newCTX); void tmd_gf_mul_x86ni(block128 *res, block128 *a_, block128 *b_); #endif #endif #endif cipher-aes128-0.7.0.3/cbits/aes_x86ni_impl.c0000644000000000000000000002547712761471030016435 0ustar0000000000000000/* * Copyright (c) 2012-2013 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ void SIZED(tmd_aes_ni_encrypt_block)(aes_block *out, aes_key *key, aes_block *in) { __m128i *k = (__m128i *) key->data; PRELOAD_ENC(k); __m128i m = _mm_loadu_si128((__m128i *) in); DO_ENC_BLOCK(m); _mm_storeu_si128((__m128i *) out, m); } void SIZED(tmd_aes_ni_decrypt_block)(aes_block *out, aes_key *key, aes_block *in) { __m128i *k = (__m128i *) key->data; PRELOAD_DEC(k); __m128i m = _mm_loadu_si128((__m128i *) in); DO_DEC_BLOCK(m); _mm_storeu_si128((__m128i *) out, m); } void SIZED(tmd_aes_ni_encrypt_ecb)(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks) { __m128i *k = (__m128i *) key->data; PRELOAD_ENC(k); for (; blocks-- > 0; in += 1, out += 1) { __m128i m = _mm_loadu_si128((__m128i *) in); DO_ENC_BLOCK(m); _mm_storeu_si128((__m128i *) out, m); } } void SIZED(tmd_aes_ni_decrypt_ecb)(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks) { __m128i *k = (__m128i *) key->data; PRELOAD_DEC(k); for (; blocks-- > 0; in += 1, out += 1) { __m128i m = _mm_loadu_si128((__m128i *) in); DO_DEC_BLOCK(m); _mm_storeu_si128((__m128i *) out, m); } } void SIZED(tmd_aes_ni_encrypt_cbc)(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks) { __m128i *k = (__m128i *) key->data; __m128i iv = _mm_loadu_si128((__m128i *) _iv); PRELOAD_ENC(k); for (; blocks-- > 0; in += 1, out += 1) { __m128i m = _mm_loadu_si128((__m128i *) in); m = _mm_xor_si128(m, iv); DO_ENC_BLOCK(m); iv = m; _mm_storeu_si128((__m128i *) out, m); } } void SIZED(tmd_aes_ni_decrypt_cbc)(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks) { __m128i *k = (__m128i *) key->data; __m128i iv = _mm_loadu_si128((__m128i *) _iv); PRELOAD_DEC(k); for (; blocks-- > 0; in += 1, out += 1) { __m128i m = _mm_loadu_si128((__m128i *) in); __m128i ivnext = m; DO_DEC_BLOCK(m); m = _mm_xor_si128(m, iv); _mm_storeu_si128((__m128i *) out, m); iv = ivnext; } } void SIZED(tmd_aes_ni_encrypt_ctr)(uint8_t *output, aes_key *key, aes_block *_iv, aes_block *newIV, uint8_t *input, uint32_t len) { __m128i *k = (__m128i *) key->data; __m128i bswap_mask = _mm_setr_epi8(7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8); __m128i one = _mm_set_epi32(0,1,0,0); uint32_t nb_blocks = len / 16; uint32_t part_block_len = len % 16; /* get the IV in little endian format */ __m128i iv = _mm_loadu_si128((__m128i *) _iv); iv = _mm_shuffle_epi8(iv, bswap_mask); PRELOAD_ENC(k); for (; nb_blocks-- > 0; output += 16, input += 16) { /* put back the iv in big endian mode, * encrypt it and and xor it the input block */ __m128i tmp = _mm_shuffle_epi8(iv, bswap_mask); DO_ENC_BLOCK(tmp); __m128i m = _mm_loadu_si128((__m128i *) input); m = _mm_xor_si128(m, tmp); _mm_storeu_si128((__m128i *) output, m); /* iv += 1 */ iv = _mm_add_epi64(iv, one); } if (part_block_len != 0) { aes_block block; memset(&block.b, 0, 16); memcpy(&block.b, input, part_block_len); __m128i m = _mm_loadu_si128((__m128i *) &block); __m128i tmp = _mm_shuffle_epi8(iv, bswap_mask); DO_ENC_BLOCK(tmp); m = _mm_xor_si128(m, tmp); _mm_storeu_si128((__m128i *) &block.b, m); memcpy(output, &block.b, part_block_len); iv = _mm_add_epi64(iv, one); } __m128i tmpRet = _mm_shuffle_epi8(iv, bswap_mask); _mm_storeu_si128((__m128i *) newIV, tmpRet); return ; } void SIZED(tmd_aes_ni_encrypt_xts)(aes_block *out, aes_key *key1, aes_key *key2, aes_block *_tweak, uint32_t spoint, aes_block *in, uint32_t blocks) { __m128i tweak = _mm_loadu_si128((__m128i *) _tweak); do { __m128i *k2 = (__m128i *) key2->data; PRELOAD_ENC(k2); DO_ENC_BLOCK(tweak); while (spoint-- > 0) tweak = gfmulx(tweak); } while (0) ; do { __m128i *k1 = (__m128i *) key1->data; PRELOAD_ENC(k1); for ( ; blocks-- > 0; in += 1, out += 1, tweak = gfmulx(tweak)) { __m128i m = _mm_loadu_si128((__m128i *) in); m = _mm_xor_si128(m, tweak); DO_ENC_BLOCK(m); m = _mm_xor_si128(m, tweak); _mm_storeu_si128((__m128i *) out, m); } } while (0); } void SIZED(tmd_aes_ni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_ctx *ctx, aes_key *key, uint8_t *input, uint32_t length, aes_ctx *newCTX) { memcpy(newCTX, ctx, sizeof(aes_ctx)); __m128i *k = (__m128i *) key->data; __m128i bswap_mask = _mm_setr_epi8(7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8); __m128i one = _mm_set_epi32(0,1,0,0); uint32_t nb_blocks = length / 16; uint32_t part_block_len = length % 16; newCTX->length_input += length; __m128i h = _mm_loadu_si128((__m128i *) &gcm->h); __m128i tag = _mm_loadu_si128((__m128i *) &newCTX->tag); __m128i iv = _mm_loadu_si128((__m128i *) &newCTX->civ); iv = _mm_shuffle_epi8(iv, bswap_mask); PRELOAD_ENC(k); for (; nb_blocks-- > 0; output += 16, input += 16) { /* iv += 1 */ iv = _mm_add_epi64(iv, one); /* put back iv in big endian, encrypt it, * and xor it to input */ __m128i tmp = _mm_shuffle_epi8(iv, bswap_mask); DO_ENC_BLOCK(tmp); __m128i m = _mm_loadu_si128((__m128i *) input); m = _mm_xor_si128(m, tmp); tag = ghash_add(tag, h, m); /* store it out */ _mm_storeu_si128((__m128i *) output, m); } if (part_block_len > 0) { __m128i mask; aes_block block; /* FIXME could do something a bit more clever (slli & sub & and maybe) ... */ switch (part_block_len) { case 1: mask = _mm_setr_epi8(0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 2: mask = _mm_setr_epi8(0,1,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 3: mask = _mm_setr_epi8(0,1,2,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 4: mask = _mm_setr_epi8(0,1,2,3,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 5: mask = _mm_setr_epi8(0,1,2,3,4,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 6: mask = _mm_setr_epi8(0,1,2,3,4,5,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 7: mask = _mm_setr_epi8(0,1,2,3,4,5,6,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 8: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 9: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,0x80,0x80,0x80,0x80,0x80,0x80,0x80); break; case 10: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,0x80,0x80,0x80,0x80,0x80,0x80); break; case 11: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,0x80,0x80,0x80,0x80,0x80); break; case 12: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,11,0x80,0x80,0x80,0x80); break; case 13: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,0x80,0x80,0x80); break; case 14: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,0x80,0x80); break; case 15: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0x80); break; default: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); break; } memset(&block.b, 0, 16); memcpy(&block.b, input, part_block_len); /* iv += 1 */ iv = _mm_add_epi64(iv, one); /* put back iv in big endian mode, encrypt it and xor it with input */ __m128i tmp = _mm_shuffle_epi8(iv, bswap_mask); DO_ENC_BLOCK(tmp); __m128i m = _mm_loadu_si128((__m128i *) &block); m = _mm_xor_si128(m, tmp); m = _mm_shuffle_epi8(m, mask); tag = ghash_add(tag, h, m); /* make output */ _mm_storeu_si128((__m128i *) &block.b, m); memcpy(output, &block.b, part_block_len); } /* store back IV & tag */ __m128i tmp = _mm_shuffle_epi8(iv, bswap_mask); _mm_storeu_si128((__m128i *) &newCTX->civ, tmp); _mm_storeu_si128((__m128i *) &newCTX->tag, tag); } cipher-aes128-0.7.0.3/cbits/bitfn.h0000644000000000000000000001523212761471030014703 0ustar0000000000000000/* * Copyright (C) 2006-2009 Vincent Hanquez * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef BITFN_H #define BITFN_H #include #ifndef NO_INLINE_ASM /**********************************************************/ # if (defined(__i386__)) # define ARCH_HAS_SWAP32 static inline uint32_t bitfn_swap32(uint32_t a) { asm ("bswap %0" : "=r" (a) : "0" (a)); return a; } /**********************************************************/ # elif (defined(__arm__)) # define ARCH_HAS_SWAP32 static inline uint32_t bitfn_swap32(uint32_t a) { uint32_t tmp = a; asm volatile ("eor %1, %0, %0, ror #16\n" "bic %1, %1, #0xff0000\n" "mov %0, %0, ror #8\n" "eor %0, %0, %1, lsr #8\n" : "=r" (a), "=r" (tmp) : "0" (a), "1" (tmp)); return a; } /**********************************************************/ # elif defined(__x86_64__) # define ARCH_HAS_SWAP32 # define ARCH_HAS_SWAP64 static inline uint32_t bitfn_swap32(uint32_t a) { asm ("bswap %0" : "=r" (a) : "0" (a)); return a; } static inline uint64_t bitfn_swap64(uint64_t a) { asm ("bswap %0" : "=r" (a) : "0" (a)); return a; } # endif #endif /* NO_INLINE_ASM */ /**********************************************************/ #ifndef ARCH_HAS_ROL32 static inline uint32_t rol32(uint32_t word, uint32_t shift) { return (word << shift) | (word >> (32 - shift)); } #endif #ifndef ARCH_HAS_ROR32 static inline uint32_t ror32(uint32_t word, uint32_t shift) { return (word >> shift) | (word << (32 - shift)); } #endif #ifndef ARCH_HAS_ROL64 static inline uint64_t rol64(uint64_t word, uint32_t shift) { return (word << shift) | (word >> (64 - shift)); } #endif #ifndef ARCH_HAS_ROR64 static inline uint64_t ror64(uint64_t word, uint32_t shift) { return (word >> shift) | (word << (64 - shift)); } #endif #ifndef ARCH_HAS_SWAP32 static inline uint32_t bitfn_swap32(uint32_t a) { return (a << 24) | ((a & 0xff00) << 8) | ((a >> 8) & 0xff00) | (a >> 24); } #endif #ifndef ARCH_HAS_ARRAY_SWAP32 static inline void array_swap32(uint32_t *d, uint32_t *s, uint32_t nb) { while (nb--) *d++ = bitfn_swap32(*s++); } #endif #ifndef ARCH_HAS_SWAP64 static inline uint64_t bitfn_swap64(uint64_t a) { return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) | (((uint64_t) bitfn_swap32((uint32_t) a)) << 32); } #endif #ifndef ARCH_HAS_ARRAY_SWAP64 static inline void array_swap64(uint64_t *d, uint64_t *s, uint32_t nb) { while (nb--) *d++ = bitfn_swap64(*s++); } #endif #ifndef ARCH_HAS_MEMORY_ZERO static inline void memory_zero(void *ptr, uint32_t len) { uint32_t *ptr32 = ptr; uint8_t *ptr8; int i; for (i = 0; i < len / 4; i++) *ptr32++ = 0; if (len % 4) { ptr8 = (uint8_t *) ptr32; for (i = len % 4; i >= 0; i--) ptr8[i] = 0; } } #endif #ifndef ARCH_HAS_ARRAY_COPY32 static inline void array_copy32(uint32_t *d, uint32_t *s, uint32_t nb) { while (nb--) *d++ = *s++; } #endif #ifndef ARCH_HAS_ARRAY_COPY64 static inline void array_copy64(uint64_t *d, uint64_t *s, uint32_t nb) { while (nb--) *d++ = *s++; } #endif #ifdef __MINGW32__ # define LITTLE_ENDIAN 1234 # define BYTE_ORDER LITTLE_ENDIAN #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) # include #elif defined(__OpenBSD__) || defined(__SVR4) # include #elif defined(__APPLE__) # include #elif defined( BSD ) && ( BSD >= 199103 ) # include #elif defined( __QNXNTO__ ) && defined( __LITTLEENDIAN__ ) # define LITTLE_ENDIAN 1234 # define BYTE_ORDER LITTLE_ENDIAN #elif defined( __QNXNTO__ ) && defined( __BIGENDIAN__ ) # define BIG_ENDIAN 1234 # define BYTE_ORDER BIG_ENDIAN #else # include #endif /* big endian to cpu */ #if LITTLE_ENDIAN == BYTE_ORDER # define be32_to_cpu(a) bitfn_swap32(a) # define cpu_to_be32(a) bitfn_swap32(a) # define le32_to_cpu(a) (a) # define cpu_to_le32(a) (a) # define be64_to_cpu(a) bitfn_swap64(a) # define cpu_to_be64(a) bitfn_swap64(a) # define le64_to_cpu(a) (a) # define cpu_to_le64(a) (a) # define cpu_to_le32_array(d, s, l) array_copy32(d, s, l) # define le32_to_cpu_array(d, s, l) array_copy32(d, s, l) # define cpu_to_be32_array(d, s, l) array_swap32(d, s, l) # define be32_to_cpu_array(d, s, l) array_swap32(d, s, l) # define cpu_to_le64_array(d, s, l) array_copy64(d, s, l) # define le64_to_cpu_array(d, s, l) array_copy64(d, s, l) # define cpu_to_be64_array(d, s, l) array_swap64(d, s, l) # define be64_to_cpu_array(d, s, l) array_swap64(d, s, l) # define ror32_be(a, s) rol32(a, s) # define rol32_be(a, s) ror32(a, s) # define ARCH_IS_LITTLE_ENDIAN #elif BIG_ENDIAN == BYTE_ORDER # define be32_to_cpu(a) (a) # define cpu_to_be32(a) (a) # define be64_to_cpu(a) (a) # define cpu_to_be64(a) (a) # define le64_to_cpu(a) bitfn_swap64(a) # define cpu_to_le64(a) bitfn_swap64(a) # define le32_to_cpu(a) bitfn_swap32(a) # define cpu_to_le32(a) bitfn_swap32(a) # define cpu_to_le32_array(d, s, l) array_swap32(d, s, l) # define le32_to_cpu_array(d, s, l) array_swap32(d, s, l) # define cpu_to_be32_array(d, s, l) array_copy32(d, s, l) # define be32_to_cpu_array(d, s, l) array_copy32(d, s, l) # define cpu_to_le64_array(d, s, l) array_swap64(d, s, l) # define le64_to_cpu_array(d, s, l) array_swap64(d, s, l) # define cpu_to_be64_array(d, s, l) array_copy64(d, s, l) # define be64_to_cpu_array(d, s, l) array_copy64(d, s, l) # define ror32_be(a, s) ror32(a, s) # define rol32_be(a, s) rol32(a, s) # define ARCH_IS_BIG_ENDIAN #else # error "endian not supported" #endif #endif /* !BITFN_H */ cipher-aes128-0.7.0.3/cbits/block128.h0000644000000000000000000000552012761471030015125 0ustar0000000000000000/* * Copyright (c) 2012 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef BLOCK128_H #define BLOCK128_H #include "bitfn.h" typedef union { uint64_t q[2]; uint32_t d[4]; uint16_t w[8]; uint8_t b[16]; } block128; static inline void block128_copy_bytes(block128 *block, const uint8_t *src, uint32_t len) { int i; for (i = 0; i < len; i++) block->b[i] = src[i]; } static inline void block128_copy(block128 *d, const block128 *s) { d->q[0] = s->q[0]; d->q[1] = s->q[1]; } static inline void block128_zero(block128 *d) { d->q[0] = 0; d->q[1] = 0; } static inline void block128_xor(block128 *d, const block128 *s) { d->q[0] ^= s->q[0]; d->q[1] ^= s->q[1]; } static inline void block128_vxor(block128 *d, block128 *s1, block128 *s2) { d->q[0] = s1->q[0] ^ s2->q[0]; d->q[1] = s1->q[1] ^ s2->q[1]; } static inline void block128_xor_bytes(block128 *block, const uint8_t *src, uint32_t len) { int i; for (i = 0; i < len; i++) block->b[i] ^= src[i]; } static inline void block128_inc_be(block128 *b) { uint64_t v = be64_to_cpu(b->q[1]); if (++v == 0) { b->q[0] = cpu_to_be64(be64_to_cpu(b->q[0]) + 1); b->q[1] = 0; } else b->q[1] = cpu_to_be64(v); } #ifdef IMPL_DEBUG #include static inline void block128_print(block128 *b) { int i; for (i = 0; i < 16; i++) { printf("%02x ", b->b[i]); } printf("\n"); } #endif #endif cipher-aes128-0.7.0.3/cbits/cpu.c0000644000000000000000000000453212761471030014364 0ustar0000000000000000/* * Copyright (C) 2012 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "cpu.h" #include #ifdef ARCH_X86 static void cpuid(uint32_t info, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { *eax = info; asm volatile ( #ifdef __x86_64__ "mov %%rbx, %%rdi;" #else "mov %%ebx, %%edi;" #endif "cpuid;" "mov %%ebx, %%esi;" #ifdef __x86_64__ "mov %%rdi, %%rbx;" #else "mov %%edi, %%ebx;" #endif :"+a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx) : :"edi"); } #ifdef USE_AESNI void tmd_initialize_hw(void (*init_table)(int, int)) { static int inited = 0; if (inited == 0) { uint32_t eax, ebx, ecx, edx; int aesni, pclmul; inited = 1; cpuid(1, &eax, &ebx, &ecx, &edx); aesni = (ecx & 0x02000000); pclmul = (ecx & 0x00000001); init_table(aesni, pclmul); } } #else #define initialize_hw(init_table) (0) #endif #endif cipher-aes128-0.7.0.3/cbits/cpu.h0000644000000000000000000000344212761471030014370 0ustar0000000000000000/* * Copyright (C) 2012 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef CPU_H #define CPU_H #if defined(__i386__) || defined(__x86_64__) #define ARCH_X86 #define USE_AESNI #endif #ifdef USE_AESNI void tmd_initialize_hw(void (*init_table)(int, int)); #else #define initialize_hw(init_table) (0) #endif #endif cipher-aes128-0.7.0.3/cbits/gf.c0000644000000000000000000000512312761471030014166 0ustar0000000000000000/* * Copyright (c) 2012 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include "cpu.h" #include "gf.h" #include "aes_x86ni.h" /* this is a really inefficient way to GF multiply. * the alternative without hw accel is building small tables * to speed up the multiplication. * TODO: optimise with tables */ void tmd_gf_mul(block128 *a, const block128 *b) { uint64_t a0, a1, v0, v1; int i, j; a0 = a1 = 0; v0 = cpu_to_be64(a->q[0]); v1 = cpu_to_be64(a->q[1]); for (i = 0; i < 16; i++) for (j = 0x80; j != 0; j >>= 1) { uint8_t x = b->b[i] & j; a0 ^= x ? v0 : 0; a1 ^= x ? v1 : 0; x = (uint8_t) v1 & 1; v1 = (v1 >> 1) | (v0 << 63); v0 = (v0 >> 1) ^ (x ? (0xe1ULL << 56) : 0); } a->q[0] = cpu_to_be64(a0); a->q[1] = cpu_to_be64(a1); } /* inplace GFMUL for xts mode */ void tmd_gf_mulx(block128 *a) { const uint64_t gf_mask = cpu_to_le64(0x8000000000000000ULL); uint64_t r = ((a->q[1] & gf_mask) ? cpu_to_le64(0x87) : 0); a->q[1] = cpu_to_le64((le64_to_cpu(a->q[1]) << 1) | (a->q[0] & gf_mask ? 1 : 0)); a->q[0] = cpu_to_le64(le64_to_cpu(a->q[0]) << 1) ^ r; } cipher-aes128-0.7.0.3/cbits/gf.h0000644000000000000000000000334712761471030014201 0ustar0000000000000000/* * Copyright (c) 2012 Vincent Hanquez * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _GF128MUL_H #define _GF128MUL_H #include "block128.h" void tmd_gf_mul(block128 *a, const block128 *b); void tmd_gf_mulx(block128 *a); #endif cipher-aes128-0.7.0.3/cbits/LICENSE0000644000000000000000000000273112761471030014435 0ustar0000000000000000Copyright (c) 2008-2013 Vincent Hanquez All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the author nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cipher-aes128-0.7.0.3/Crypto/0000755000000000000000000000000012761471030013601 5ustar0000000000000000cipher-aes128-0.7.0.3/Crypto/Cipher/0000755000000000000000000000000012761471030015013 5ustar0000000000000000cipher-aes128-0.7.0.3/Crypto/Cipher/AES128.hs0000644000000000000000000002471212761471030016220 0ustar0000000000000000{-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE RecordWildCards #-} module Crypto.Cipher.AES128 ( -- * Key types with crypto-api instances AESKey128, AESKey192, AESKey256 , BlockCipher(..), buildKeyIO, zeroIV -- * GCM Operations , makeGCMCtx, aesKeyToGCM, GCMCtx, AuthTag(..), AES_GCM , Crypto.Cipher.AES128.encryptGCM , Crypto.Cipher.AES128.decryptGCM ) where import Crypto.Cipher.AES128.Internal as I import Crypto.Classes import Data.Function (on) import Control.Monad (when) import Data.Serialize import Data.Tagged import Data.Word (Word8) import Foreign.Ptr import Foreign.ForeignPtr import Foreign.Marshal.Alloc as F import System.IO.Unsafe import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Internal as B import qualified Data.ByteString.Unsafe as B instance Serialize AESKey128 where put k = do let RKey128 l h = (rawKey128 k) putWord64be h putWord64be l get = do b <- getByteString 16 case buildKey b of Nothing -> fail "Invalid key on 'get'" Just k -> return k instance Serialize AESKey192 where put k = do let RKey192 a b c = (rawKey192 k) putWord64be c putWord64be b putWord64be a get = do b <- getByteString 24 case buildKey b of Nothing -> fail "Invalid key on 'get'" Just k -> return k instance Serialize AESKey256 where put k = do let RKey256 a b c d = (rawKey256 k) putWord64be d putWord64be c putWord64be b putWord64be a get = do b <- getByteString 32 case buildKey b of Nothing -> fail "Invalid key on 'get'" Just k -> return k instance BlockCipher AESKey128 where blockSize = Tagged 128 keyLength = Tagged 128 buildKey bs | B.length bs >= 16 = unsafePerformIO $ B.unsafeUseAsCString bs (\p -> generateKey128 (castPtr p)) | otherwise = Nothing encryptBlock k b = unsafePerformIO $ do B.unsafeUseAsCStringLen b $ \(inP,len) -> do B.create (B.length b) $ \outP -> do encryptECB k (castPtr outP) (castPtr inP) (len`div`blkSize) decryptBlock k b = unsafePerformIO $ do B.unsafeUseAsCStringLen b $ \(inP,len) -> do B.create (B.length b) $ \outP -> do decryptECB k (castPtr outP) (castPtr inP) (len`div`blkSize) ecb = encryptBlock unEcb = decryptBlock ctr k (IV bs) pt = unsafePerformIO $ do B.unsafeUseAsCStringLen pt $ \(inP, len) -> do B.unsafeUseAsCStringLen bs $ \(ivP, ivLen) -> do when (ivLen /= (blockSizeBytes .::. k)) (error "Cipher-AES128: IV wrong length! They type system would have/should have caught this if you didn't use the IV constructor...") newIVFP <- B.mallocByteString ivLen ct <- B.create len $ \outP -> withForeignPtr newIVFP $ \newIVP -> do encryptCTR k (castPtr ivP) (castPtr newIVP) (castPtr outP) (castPtr inP) len let newIV = B.fromForeignPtr newIVFP 0 ivLen return (ct,IV newIV) {-# INLINE ctr #-} unCtr = ctr blkSize :: Int blkSize = 16 instance BlockCipher AESKey192 where blockSize = Tagged 128 keyLength = Tagged 192 buildKey bs | B.length bs >= 16 = unsafePerformIO $ B.unsafeUseAsCString bs (\p -> generateKey192 (castPtr p)) | otherwise = Nothing encryptBlock k b = unsafePerformIO $ do B.unsafeUseAsCStringLen b $ \(inP,len) -> do B.create (B.length b) $ \outP -> do encryptECB k (castPtr outP) (castPtr inP) (len`div`blkSize) decryptBlock k b = unsafePerformIO $ do B.unsafeUseAsCStringLen b $ \(inP,len) -> do B.create (B.length b) $ \outP -> do decryptECB k (castPtr outP) (castPtr inP) (len`div`blkSize) ecb = encryptBlock unEcb = decryptBlock ctr k (IV bs) pt = unsafePerformIO $ do B.unsafeUseAsCStringLen pt $ \(inP, len) -> do B.unsafeUseAsCStringLen bs $ \(ivP, ivLen) -> do when (ivLen /= (blockSizeBytes .::. k)) (error "Cipher-AES128: IV wrong length! They type system would have/should have caught this if you didn't use the IV constructor...") newIVFP <- B.mallocByteString ivLen ct <- B.create len $ \outP -> withForeignPtr newIVFP $ \newIVP -> do encryptCTR k (castPtr ivP) (castPtr newIVP) (castPtr outP) (castPtr inP) len let newIV = B.fromForeignPtr newIVFP 0 ivLen return (ct,IV newIV) {-# INLINE ctr #-} unCtr = ctr instance BlockCipher AESKey256 where blockSize = Tagged 128 keyLength = Tagged 256 buildKey bs | B.length bs >= 16 = unsafePerformIO $ B.unsafeUseAsCString bs (\p -> generateKey256 (castPtr p)) | otherwise = Nothing encryptBlock k b = unsafePerformIO $ do B.unsafeUseAsCStringLen b $ \(inP,len) -> do B.create (B.length b) $ \outP -> do encryptECB k (castPtr outP) (castPtr inP) (len`div`blkSize) decryptBlock k b = unsafePerformIO $ do B.unsafeUseAsCStringLen b $ \(inP,len) -> do B.create (B.length b) $ \outP -> do decryptECB k (castPtr outP) (castPtr inP) (len`div`blkSize) ecb = encryptBlock unEcb = decryptBlock ctr k (IV bs) pt = unsafePerformIO $ do B.unsafeUseAsCStringLen pt $ \(inP, len) -> do B.unsafeUseAsCStringLen bs $ \(ivP, ivLen) -> do when (ivLen /= (blockSizeBytes .::. k)) (error "Cipher-AES128: IV wrong length! They type system would have/should have caught this if you didn't use the IV constructor...") newIVFP <- B.mallocByteString ivLen ct <- B.create len $ \outP -> withForeignPtr newIVFP $ \newIVP -> do encryptCTR k (castPtr ivP) (castPtr newIVP) (castPtr outP) (castPtr inP) len let newIV = B.fromForeignPtr newIVFP 0 ivLen return (ct,IV newIV) {-# INLINE ctr #-} unCtr = ctr -- GCM Routines maxTagLen :: Int maxTagLen = 16 data AuthTag = AuthTag { unAuthTag :: ByteString } -- | A tuple of key and precomputed data for use by GCM data GCMCtx k = GCMCtx { gcmkey :: k , gcmpc :: GCMpc } instance Eq AuthTag where (==) = constTimeEq `on` unAuthTag -- A super-class indicating which keys can be used with GCMCtx. class (BlockCipher k, GetExpanded k) => AES_GCM k where instance AES_GCM AESKey128 instance AES_GCM AESKey192 instance AES_GCM AESKey256 -- | Given key material produce a context useful for GCM operations makeGCMCtx :: AES_GCM k => ByteString -> Maybe (GCMCtx k) makeGCMCtx = fmap aesKeyToGCM . buildKey -- | Given an AESKey produce a GCM Context. aesKeyToGCM :: AES_GCM k => k -> GCMCtx k aesKeyToGCM k = GCMCtx k (I.precomputeGCMdata k) -- |Encrypts multiple-of-block-sized input, returning a bytestring and tag. encryptGCM :: AES_GCM k => GCMCtx k -> ByteString -- ^ IV -> ByteString -- ^ Plaintext -> ByteString -- ^ AAD -> (ByteString, AuthTag) encryptGCM key iv pt aad = unsafePerformIO $ do B.unsafeUseAsCString pt $ \ptPtr -> do B.unsafeUseAsCString iv $ \ivPtr -> do B.unsafeUseAsCString aad $ \aadPtr -> do ctPtr <- F.mallocBytes (B.length pt) tagPtr <- F.mallocBytes maxTagLen encryptGCMPtr key (castPtr ivPtr) (B.length iv) (castPtr ptPtr) (B.length pt) (castPtr aadPtr) (B.length aad) (castPtr ctPtr) (castPtr tagPtr) ctBS <- B.unsafePackMallocCStringLen (castPtr ctPtr, B.length pt) tagBS <- B.unsafePackMallocCStringLen (castPtr tagPtr, maxTagLen) return (ctBS, AuthTag tagBS) -- Encrypts multiple-of-block-sized input, filling a pointer with the -- result of [ctr, ct, tag]. encryptGCMPtr :: AES_GCM k => GCMCtx k -> Ptr Word8 -- ^ IV -> Int -- ^ IV Length -> Ptr Word8 -- ^ Plaintext buffer -> Int -- ^ Plaintext length -> Ptr Word8 -- ^ AAD buffer -> Int -- ^ AAD Length -> Ptr Word8 -- ^ ciphertext buffer (at least encBytes large) -> Ptr Word8 -- ^ Tag buffer (always allocated to max length) -> IO () encryptGCMPtr (GCMCtx {..}) ivPtr ivLen ptPtr ptLen aadPtr aadLen ctPtr tagPtr = do I.encryptGCM gcmkey gcmpc (castPtr ivPtr) (fromIntegral ivLen) (castPtr aadPtr) (fromIntegral aadLen) (castPtr ptPtr) (fromIntegral ptLen) (castPtr ctPtr) (castPtr tagPtr) -- | Decrypts multiple-of-block-sized input, returing a bytestring of the -- [ctr, ct, tag]. decryptGCM :: AES_GCM k => GCMCtx k -> ByteString -- ^ IV -> ByteString -- ^ Ciphertext -> ByteString -- ^ AAD -> (ByteString, AuthTag) -- ^ Plaintext and incremented context (or an error) decryptGCM gcmdata iv ct aad = unsafePerformIO $ do let ivLen = B.length iv tagLen = maxTagLen ctLen = B.length ct B.unsafeUseAsCString iv $ \ivPtr -> do B.unsafeUseAsCString ct $ \ctPtr -> do B.unsafeUseAsCString aad $ \aadPtr -> do tagPtr <- F.mallocBytes tagLen ptPtr <- F.mallocBytes ctLen decryptGCM_ptr gcmdata (castPtr ivPtr) ivLen (castPtr ctPtr) ctLen (castPtr aadPtr) (B.length aad) (castPtr ptPtr) (castPtr tagPtr) tagBS <- B.unsafePackMallocCStringLen (castPtr tagPtr,tagLen) ptBS <- B.unsafePackMallocCStringLen (castPtr ptPtr, ctLen) return (ptBS, AuthTag tagBS) decryptGCM_ptr :: AES_GCM k => GCMCtx k -> Ptr Word8 -> Int -- IV -> Ptr Word8 -> Int -- CT -> Ptr Word8 -> Int -- AAD -> Ptr Word8 -- Plaintext -> Ptr Word8 -- Tag -> IO () decryptGCM_ptr (GCMCtx {..}) ivPtr ivLen ctPtr ctLen aadPtr aadLen ptPtr tagPtr = I.decryptGCM gcmkey gcmpc ivPtr (fromIntegral ivLen) aadPtr (fromIntegral aadLen) ctPtr (fromIntegral ctLen) ptPtr tagPtr cipher-aes128-0.7.0.3/Crypto/Cipher/AES128/0000755000000000000000000000000012761471030015656 5ustar0000000000000000cipher-aes128-0.7.0.3/Crypto/Cipher/AES128/Internal.hs0000644000000000000000000003560212761471030017774 0ustar0000000000000000{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls, ViewPatterns #-} module Crypto.Cipher.AES128.Internal ( AESKey128(..), AESKey192(..), AESKey256(..), RawKey128(..), RawKey192(..), RawKey256(..), GCM(..), GCMpc , generateKey128, generateKey192, generateKey256 , generateGCM, precomputeGCMdata , encryptECB , decryptECB , encryptCTR , decryptCTR , encryptGCM, decryptGCM -- * Piece-meal functions , cipherOnlyGCM , decipherOnlyGCM , finishGCM, aadGCM -- * Internal, will not be exported in a near-future release. , GetExpanded ) where import Foreign.Ptr import Foreign.ForeignPtr import Foreign.Storable import Foreign.Marshal.Alloc import Data.Word import Data.Bits (shiftL, (.|.)) import System.IO.Unsafe -- AES Bindings data AESKeyStruct type AESKeyPtr = Ptr AESKeyStruct data RawKey128 = RKey128 { lowK128,highK128 :: {-# UNPACK #-} !Word64 } data AESKey128 = AESKey128 { rawKey128 :: !RawKey128 , expandedKey128 :: ForeignPtr AESKeyStruct } data RawKey192 = RKey192 { lowK192,midK192,highK192 :: {-# UNPACK #-} !Word64 } data AESKey192 = AESKey192 { rawKey192 :: !RawKey192 , expandedKey192 :: ForeignPtr AESKeyStruct } data RawKey256 = RKey256 { aK256,bK256,cK256,dK256 :: {-# UNPACK #-} !Word64 } data AESKey256 = AESKey256 { rawKey256 :: !RawKey256 , expandedKey256 :: ForeignPtr AESKeyStruct } class GetExpanded a where expandedKey :: a -> ForeignPtr AESKeyStruct instance GetExpanded AESKey256 where expandedKey = expandedKey256 instance GetExpanded AESKey192 where expandedKey = expandedKey192 instance GetExpanded AESKey128 where expandedKey = expandedKey128 type AESGcmPtr = Ptr GCMStruct data GCMStruct -- Store the key, the precomputed GCM data, and the current IV by way of -- a foreign pointer data GCM k = GCM { _gcmFP :: GCMpc , _keyFP :: k , _ctxFP2 :: ForeignPtr CTXStruct } newtype GCMpc = GCMpc { unGCMpc :: ForeignPtr GCMStruct } type AESCtxPtr = Ptr CTXStruct data CTXStruct -- data CTX = CTX { _ctxFP :: ForeignPtr CTXStruct } foreign import ccall unsafe "aes.h tmd_aes_initkey" c_aes_initkey :: AESKeyPtr -> Ptr Word8 -> Word8 -> IO () foreign import ccall unsafe "aes.h tmd_allocatekey" c_allocate_key :: IO AESKeyPtr foreign import ccall unsafe "aes.h &tmd_freekey" c_free_key :: FunPtr (AESKeyPtr -> IO ()) -- foreign import ccall unsafe "aes.h tmd_freekey" -- c_key_free :: AESKeyPtr -> IO () foreign import ccall unsafe "aes.h tmd_allocatectx" c_allocate_ctx :: IO AESCtxPtr foreign import ccall unsafe "aes.h &tmd_freectx" c_free_ctx :: FunPtr (AESCtxPtr -> IO ()) -- foreign import ccall unsafe "aes.h tmd_freectx" -- c_ctx_free :: AESCtxPtr -> IO () foreign import ccall unsafe "aes.h tmd_allocategcm" c_allocate_gcm :: IO AESGcmPtr foreign import ccall unsafe "aes.h &tmd_freegcm" c_free_gcm :: FunPtr (AESGcmPtr -> IO ()) -- foreign import ccall unsafe "aes.h tmd_freegcm" -- c_gcm_free :: AESGcmPtr -> IO () foreign import ccall unsafe "aes.h tmd_aes_gcm_init" c_gcm_init :: AESGcmPtr -> AESKeyPtr -> IO () foreign import ccall unsafe "aes.h tmd_aes_ctx_init" c_ctx_init :: AESGcmPtr -> AESCtxPtr -> AESKeyPtr -> Ptr Word8 -> Word32 -- ^ IV and length -> IO () foreign import ccall unsafe "aes.h tmd_aes_encrypt_ecb" c_encrypt_ecb :: Ptr Word8 -> AESKeyPtr -> Ptr Word8 -> Word32 -> IO () foreign import ccall unsafe "aes.h tmd_aes_decrypt_ecb" c_decrypt_ecb :: Ptr Word8 -> AESKeyPtr -> Ptr Word8 -> Word32 -> IO () foreign import ccall unsafe "aes.h tmd_aes_gcm_finish" c_gcm_finish :: Ptr Word8 -- Tag -> AESGcmPtr -> AESKeyPtr -- Key -> AESCtxPtr -- Context -> IO () foreign import ccall unsafe "aes.h tmd_aes_gcm_aad" c_gcm_aad :: AESGcmPtr -> AESCtxPtr -> Ptr Word8 -> Word32 -- AAD, len -> IO () foreign import ccall unsafe "aes.h tmd_aes_gcm_decrypt" c_gcm_decrypt :: Ptr Word8 -- Output -> AESGcmPtr -> AESCtxPtr -> AESKeyPtr -> Ptr Word8 -> Word32 -- CT and length -> IO () foreign import ccall unsafe "aes.h tmd_aes_gcm_encrypt" c_gcm_encrypt :: Ptr Word8 -- Output -> AESGcmPtr -> AESCtxPtr -> AESKeyPtr -> Ptr Word8 -> Word32 -- PT and length -> IO () foreign import ccall unsafe "aes.h tmd_aes_gcm_full_encrypt" c_gcm_full_encrypt :: AESKeyPtr -> AESGcmPtr -> Ptr Word8 -> Word32 -- IV, IVLen -> Ptr Word8 -> Word32 -- AAD, AADLen -> Ptr Word8 -> Word32 -- PT, PTLen -> Ptr Word8 -- CT -> Ptr Word8 -- Tag -> IO () foreign import ccall unsafe "aes.h tmd_aes_gcm_full_decrypt" c_gcm_full_decrypt :: AESKeyPtr -> AESGcmPtr -> Ptr Word8 -> Word32 -- IV, IVLen -> Ptr Word8 -> Word32 -- AAD, AADLen -> Ptr Word8 -> Word32 -- PT, PTLen -> Ptr Word8 -- CT -> Ptr Word8 -- Tag -> IO () foreign import ccall unsafe "aes.h tmd_aes_encrypt_ctr" c_encrypt_ctr :: Ptr Word8 -- ^ Output -> AESKeyPtr -> Ptr Word8 -- ^ 128 bit IV -> Ptr Word8 -- ^ 128 bit new IV -> Ptr Word8 -- ^ Input -> Word32 -- ^ Input length in bytes -> IO () c_decrypt_ctr :: Ptr Word8 -- ^ Result -> AESKeyPtr -> Ptr Word8 -- ^ 128 bit IV -> Ptr Word8 -- ^ 128 bit new IV -> Ptr Word8 -- ^ Input -> Word32 -- ^ Input length in bytes -> IO () c_decrypt_ctr = c_encrypt_ctr blkSzC :: Word32 blkSzC = 16 -- Given a 16 byte buffer, allocate and return an AESKey generateKey128 :: Ptr Word64 -- ^ Buffer of 16 bytes of key material -> IO (Maybe AESKey128) generateKey128 keyPtr = do raw <- do a <- peekLE (castPtr keyPtr) let keyPtr2 = (castPtr keyPtr) `plusPtr` sizeOf a b <- peekLE keyPtr2 return (RKey128 b a) k <- c_allocate_key c_aes_initkey k (castPtr keyPtr) 16 fmap (Just . AESKey128 raw) (newForeignPtr c_free_key k) where peekLE :: Ptr Word8 -> IO Word64 peekLE p = do a1 <- peekElemOff p 0 a2 <- peekElemOff p 1 a3 <- peekElemOff p 2 a4 <- peekElemOff p 3 a5 <- peekElemOff p 4 a6 <- peekElemOff p 5 a7 <- peekElemOff p 6 a8 <- peekElemOff p 7 let f n s = fromIntegral n `shiftL` s let a = (f a1 56) .|. (f a2 48) .|. (f a3 40) .|. (f a4 32) .|. (f a5 24) .|. (f a6 16) .|. (f a7 8) .|. fromIntegral a8 return a {-# INLINE generateKey128 #-} -- Given a 16 byte buffer, allocate and return an AESKey generateKey192 :: Ptr Word64 -- ^ Buffer of 16 bytes of key material -> IO (Maybe AESKey192) generateKey192 keyPtr = do raw <- do a <- peekLE (castPtr keyPtr) let keyPtr2 = (castPtr keyPtr) `plusPtr` sizeOf a b <- peekLE keyPtr2 let keyPtr3 = (castPtr keyPtr) `plusPtr` sizeOf a `plusPtr` sizeOf b c <- peekLE keyPtr3 return (RKey192 c b a) k <- c_allocate_key c_aes_initkey k (castPtr keyPtr) 24 fmap (Just . AESKey192 raw) (newForeignPtr c_free_key k) where peekLE :: Ptr Word8 -> IO Word64 peekLE p = do a1 <- peekElemOff p 0 a2 <- peekElemOff p 1 a3 <- peekElemOff p 2 a4 <- peekElemOff p 3 a5 <- peekElemOff p 4 a6 <- peekElemOff p 5 a7 <- peekElemOff p 6 a8 <- peekElemOff p 7 let f n s = fromIntegral n `shiftL` s let a = (f a1 56) .|. (f a2 48) .|. (f a3 40) .|. (f a4 32) .|. (f a5 24) .|. (f a6 16) .|. (f a7 8) .|. fromIntegral a8 return a {-# INLINE generateKey192 #-} -- Given a 16 byte buffer, allocate and return an AESKey generateKey256 :: Ptr Word64 -- ^ Buffer of 16 bytes of key material -> IO (Maybe AESKey256) generateKey256 keyPtr = do raw <- do a <- peekLE (castPtr keyPtr) let keyPtr2 = (castPtr keyPtr) `plusPtr` sizeOf a b <- peekLE keyPtr2 let keyPtr3 = (castPtr keyPtr) `plusPtr` sizeOf a `plusPtr` sizeOf b c <- peekLE keyPtr3 let keyPtr4 = (castPtr keyPtr) `plusPtr` sizeOf a `plusPtr` sizeOf b `plusPtr` sizeOf c d <- peekLE keyPtr4 return (RKey256 d c b a) k <- c_allocate_key c_aes_initkey k (castPtr keyPtr) 32 fmap (Just . AESKey256 raw) (newForeignPtr c_free_key k) where peekLE :: Ptr Word8 -> IO Word64 peekLE p = do a1 <- peekElemOff p 0 a2 <- peekElemOff p 1 a3 <- peekElemOff p 2 a4 <- peekElemOff p 3 a5 <- peekElemOff p 4 a6 <- peekElemOff p 5 a7 <- peekElemOff p 6 a8 <- peekElemOff p 7 let f n s = fromIntegral n `shiftL` s let a = (f a1 56) .|. (f a2 48) .|. (f a3 40) .|. (f a4 32) .|. (f a5 24) .|. (f a6 16) .|. (f a7 8) .|. fromIntegral a8 return a {-# INLINE generateKey256 #-} -- Given a 16 byte buffer, allocate and return an key expansion useful for -- GCM generateGCM :: GetExpanded k => k -> IO (GCM k) generateGCM keyStruct = do let gcmPC = precomputeGCMdata keyStruct withForeignPtr (expandedKey keyStruct) $ \k -> do c <- c_allocate_ctx allocaBytes 12 $ \ivPtr -> withGCMpc gcmPC $ \g -> do mapM_ (\i -> pokeElemOff ivPtr i (0::Word8)) [0..11] c_ctx_init g c k ivPtr 12 cFP <- newForeignPtr c_free_ctx c return (GCM gcmPC keyStruct cFP) {-# INLINE generateGCM #-} precomputeGCMdata :: GetExpanded k => k -> GCMpc precomputeGCMdata k = unsafePerformIO $ do withForeignPtr (expandedKey k) $ \kp -> do g <- c_allocate_gcm c_gcm_init g kp gFP <- newForeignPtr c_free_gcm g return (GCMpc gFP) withGCMpc :: GCMpc -> (AESGcmPtr -> IO a) -> IO a withGCMpc (GCMpc p) = withForeignPtr p -- An encrypt function that can handle up to blks < maxBound `div` 16 :: Word32 -- simultaneous blocks. encryptECB :: GetExpanded k => k -- ^ The key -> Ptr Word8 -- ^ The result buffer -> Ptr Word8 -- ^ The source buffer -> Int -- ^ The input size in blocks -> IO () encryptECB (expandedKey -> k) dst src blks = withForeignPtr k $ \p -> c_encrypt_ecb dst p src (fromIntegral blks) {-# INLINE encryptECB #-} decryptECB :: GetExpanded k => k -- ^ The key -> Ptr Word8 -- ^ The result buffer -> Ptr Word8 -- ^ The source buffer -> Int -- ^ The input size in blocks -> IO () decryptECB (expandedKey -> k) dst src blks | blks > fromIntegral (maxBound `div` blkSzC :: Word32) = error "Can not decrypt so many blocks at once" | otherwise = withForeignPtr k $ \p -> c_decrypt_ecb dst p src (fromIntegral blks) {-# INLINE decryptECB #-} aadGCM :: GetExpanded k => GCM k -> Ptr Word8 -> Int -> IO () aadGCM gcm aad aadLen = withForeignGCM gcm $ \(g,_k,c) -> c_gcm_aad g c aad (fromIntegral aadLen) cipherOnlyGCM :: GetExpanded k => GCM k -> Ptr Word8 -- CT (length assumed to match PT) -> Ptr Word8 -> Int -- PT and length -> IO () cipherOnlyGCM gcm ct pt ptlen = withForeignGCM gcm $ \(g,k,c) -> c_gcm_encrypt ct g c k pt (fromIntegral ptlen) decipherOnlyGCM :: GetExpanded k => GCM k -> Ptr Word8 -- PT (length assumed to match CT) -> Ptr Word8 -> Int -- CT and length -> IO () decipherOnlyGCM gcm pt ct ctlen = withForeignGCM gcm $ \(g,k,c) -> c_gcm_decrypt pt g c k ct (fromIntegral ctlen) finishGCM :: GetExpanded k => GCM k -- GCM context (which is mutated!) -> Ptr Word8 -- Tag, must point to 16 byte buffer (or larger) -> IO () finishGCM gcm tagPtr = withForeignGCM gcm $ \(gp,kp,cp) -> c_gcm_finish tagPtr gp kp cp withForeignGCM :: GetExpanded k => GCM k -> ((AESGcmPtr, AESKeyPtr, AESCtxPtr) -> IO a) -> IO a withForeignGCM (GCM g k c) f = withForeignPtr (unGCMpc g) $ \gp -> withForeignPtr (expandedKey k) $ \kp -> withForeignPtr c $ \cp -> f (gp,kp,cp) encryptCTR :: GetExpanded k => k -> Ptr Word8 -- ^ IV -> Ptr Word8 -- ^ NEW IV -> Ptr Word8 -- ^ CT -> Ptr Word8 -- ^ PT -> Int -- ^ Length in bytes -> IO () encryptCTR (expandedKey -> k) iv niv ct pt len = withForeignPtr k $ \p -> do c_encrypt_ctr ct p iv niv pt (fromIntegral len) {-# INLINE encryptCTR #-} decryptCTR :: GetExpanded k => k -> Ptr Word8 -- ^ IV -> Ptr Word8 -- ^ NEW IV -> Ptr Word8 -- ^ PT -> Ptr Word8 -- ^ CT -> Int -- ^ Length in bytes -> IO () decryptCTR (expandedKey -> k) iv niv pt ct len = withForeignPtr k $ \p -> do c_decrypt_ctr pt p iv niv ct (fromIntegral len) encryptGCM :: GetExpanded k => k -- AES{128,192,256} -> GCMpc -- Precomputed GCM Data -> Ptr Word8 -> Word32 -- IV, len -> Ptr Word8 -> Word32 -- AAD, len -> Ptr Word8 -> Word32 -- PT, len -> Ptr Word8 -- CT (out) -> Ptr Word8 -- Tag (128 bits out) -> IO () encryptGCM (expandedKey -> k) (GCMpc g) iv ivLen aad aadLen pt ptLen ct tag = withForeignPtr k $ \kp -> withForeignPtr g $ \gp -> c_gcm_full_encrypt kp gp iv ivLen aad aadLen pt ptLen ct tag decryptGCM :: GetExpanded k => k -> GCMpc -> Ptr Word8 -> Word32 -- IV, len -> Ptr Word8 -> Word32 -- AAD, len -> Ptr Word8 -> Word32 -- CT, len -> Ptr Word8 -- PT (out) -> Ptr Word8 -- Tag (out) -> IO () decryptGCM (expandedKey -> k) (GCMpc g) iv ivLen aad aadLen ct ctLen pt tag = withForeignPtr k $ \kp -> withForeignPtr g $ \gp -> c_gcm_full_decrypt kp gp iv ivLen aad aadLen ct ctLen pt tag {-# INLINE decryptCTR #-} cipher-aes128-0.7.0.3/Test/0000755000000000000000000000000012761471030013240 5ustar0000000000000000cipher-aes128-0.7.0.3/Test/test.hs0000644000000000000000000000034412761471030014554 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PackageImports #-} import Test.AES import Crypto.Cipher.AES128 import "test-framework" Test.Framework main = do ts <- makeAESTests (undefined :: AESKey128) defaultMain ts