An AES (Rijndael) Implementation in C/C++ (as specified in FIPS-197)

来源:互联网 发布:水利工程用什么软件 编辑:程序博客网 时间:2024/06/14 07:53
An AES (Rijndael) Implementation in C/C++ (as specified in FIPS-197)====================================================================Changes in this Version (16/04/2007)====================================These changes remove errors in the VC++ build files and add some improvements in file naming consitency and portability. There areno changes to overcome reported bugs in the code.1. gen_tabs() has been renamed to aes_init() to better decribe its   function to those not familiar with AES internals.2. via_ace.h has been renamed to aes_via_ace.h.3. Minor changes have been made to aestab.h and aestab.c to enable   all the code to be compiled in either C or C++.   4. The code for detecting memory alignment in aesmdoes.c has been   simplified and a new routine has been added:          aes_test_alignment_detection()      to check that the aligment test is likely to be correct.5. The addition of support for Structured Exception Handling (SEH)    to YASM (well done Peter and Michael!) has allowed the AMD64    x64 assembler code to be changed to comply with SEH requriements.       6. Corrections to build files (for win32 debug build).Overview========This code implements AES for both 32 and 64 bit systems with optionalassembler support for x86 and AMD64/EM64T (but optimised for AMD64).The basic AES source code files are as follows:aes.h           the header file needed to use AES in Caescpp.h        the header file required with to use AES in C++aesopt.h        the header file for setting options (and some common code)aestab.h        the header file for the AES table declarationaescrypt.c      the main C source code file for encryption and decryptionaeskey.c        the main C source code file for the key scheduleaestab.c        the main file for the AES tablesbrg_types.h     a header defining some standard types and DLL definesbrg_endian.h    a header containing code to detect or define endiannessaes_x86_v1.asm  x86 assembler (YASM) alternative to aescrypt.c using                large tablesaes_x86_v2.asm  x86 assembler (YASM) alternative to aescrypt.c using                compressed tablesaes_amd64.asm   AMD64 assembler (YASM) alternative to aescrypt.c using                compressed tablesIn addition AES modes are implemented in the files:aes_modes.c     AES modes with optional support for VIA ACE detection and useaes_via_ace.h   the header file for VIA ACE supportOther associated files for testing and support are:aesaux.h        header for auxilliary routines for testsingaesaux.c        auxilliary routines for testsingtaestst.h        header file for setting the testing environmentrdtsc.h         a header file that provides access to the Time Stamp Counteraestst.c        a simple test program for quick tests of the AES codeaesgav.c        a program to generate and verify the test vector filesaesrav.c        a program to verify output against the test vector filesaestmr.c        a program to time the code on x86 systemsmodetest.c      a program to test the AES modes supportvbxam.doc       a demonstration of AES DLL use from Visual Basic in Microsoft Wordvb.txt          Visual Basic code from the above example (win32 only)aesxam.c        an example of AES usetablegen.c      a program to generate a simplified 'aestab.c' file for                use with compilers that find aestab.c too complexyasm.rules      the YASM build rules file for Microsoft Visual Studio 2005via_ace.txt     describes support for the VIA ACE cryptography engineaes.txt         this fileBuilding The AES Libraries--------------------------A. Versions-----------The code can be used to build static and dynamic libraries, each in fiveversions:    C           uses C source code only    ASM_X86_V1C large table x86 assembler code for encrypt/decrypt    ASM_X86_V2  compressed table x86 assembler for encrypt/decrypt and keying    ASM_X86_V2C compressed table x86 assembler code for encrypt/decrypt    ASM_AMD64   compressed table x86 assembler code for encrypt/decryptThe C version can be compiled for Win32 or x64, the x86 assembler versionsare for Win32 only and the AMD64 version for x64 only.B. Types--------The code makes use of types defined as uint_<nn>t where <nn> is the lengthof the type, for example, the unsigned 32-bit type is 'uint_32t'.  These areNOT the same as the fixed width integer types in C99, inttypes.h and stdint.hsince several attempts to use these types have shown that support for them isstill highly variable.  But a regular expression search and replace in VC++with search on 'uint_{:z}t' and a replace with 'uint\1_t' will convert thesetypes to C99 types (there should be similar search/replace facilities on othersystems).C. YASM-------If you wish to use the x86 assembler files you will also need the YASM opensource x86 assembler (r1331 or later) for Windows which can be obtained from:  http://www.tortall.net/projects/yasm/This assembler should be placed in the bin directory used by VC++, which, forVisual Stduio 2005, is typically: C:\Program Files (x86)\Microsoft Visual Studio 8\VC\binYou will also need to move the yasm.rules file from this distribution intothe directory where Visual Studio 2005 expects to find it, which is typically: C:\Program Files (x86)\Microsoft Visual Studio 8\VC\VCProjectDefaultsAlternatively you can configure the path for rules files within Visual Studio.D. Configuration----------------The following configurations are available as projects for Visual Studio 2005but the following descriptions should allow them to be built in other x86environments:    lib_generic_c       Win32 and x64        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aescrypt.c, aeskey.c, aestab.c, aes_modes.c        defines    dll_generic_c       Win32 and x64        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aescrypt.c, aeskey.c, aestab.c, aes_modes.c        defines         DLL_EXPORT    lib_asm_x86_v1c     Win32        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aeskey.c, aestab.c, aes_modes.c        x86 assembler:  aes_x86_v1.asm        defines         ASM_X86_V1C (set for C and assembler files)    dll_asm_x86_v1c     Win32        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aeskey.c, aestab.c, aes_modes.c        x86 assembler:  aes_x86_v1.asm        defines         DLL_EXPORT, ASM_X86_V1C (set for C and assembler files)    lib_asm_x86_v2c     Win32        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aeskey.c, aestab.c, aes_modes.c        x86 assembler:  aes_x86_v2.asm        defines         ASM_X86_V2C (set for C and assembler files)    dll_asm_x86_v2c     Win32        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aeskey.c, aestab.c, aes_modes.c        x86 assembler:  aes_x86_v1.asm        defines         DLL_EXPORT, ASM_X86_V2C (set for C and assembler files)    lib_asm_x86_v2      Win32        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aes_modes.c        x86 assembler:  aes_x86_v1.asm        defines         ASM_X86_V2 (set for C and assembler files)    dll_asm_x86_v2      Win32        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aes_modes.c        x86 assembler:  aes_x86_v1.asm        defines         DLL_EXPORT, ASM_AMD64_C (set for C and assembler files)    lib_asm_amd64_c     x64        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aes_modes.c        x86 assembler:  aes_amd64.asm        defines         ASM_X86_V2 (set for C and assembler files)    dll_asm_amd64_c     x64        headers:        aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs,h        C source:       aes_modes.c        x86 assembler:  aes_amd64.asm        defines         DLL_EXPORT, ASM_AMD64_C (set for C and assembler files)Notes:ASM_X86_V1C is defined if using the version 1 assembler code (aescrypt1.asm).            The defines in the assember file must match those in aes.h and            aesopt.h).  Also remember to include/exclude the right assembler            and C files in the build to avoid undefined or multiply defined            symbols - include aescrypt1.asm and exclude aescrypt.c and            aescrypt2.asm.ASM_X86_V2  is defined if using the version 2 assembler code (aescrypt2.asm).            This version provides a full, self contained assembler version            and does not use any C source code files except for the mutiple            block encryption modes that are provided by aes_modes.c. The define            ASM_X86_V2 must be set on the YASM command line (or in aescrypt2.asm)            to use this version and all C files except aec_modes.c and. for the            DLL build, aestab.c must be excluded from the build.ASM_X86_V2C is defined when using the version 2 assembler code (aescrypt2.asm)            with faster key scheduling provided by the in C code (the options in            the assember file must match those in aes.h and aesopt.h).  In this            case aeskey.c and aestab.c are needed with aescrypt2.asm and the            define ASM_X86_V2C must be set for both the C files and for            asecrypt2.asm command lines (or in aesopt.h and aescrypt2.asm).            Include aescrypt2.asm aeskey.c and aestab.c, exclude aescrypt.c for            this option.ASM_AMD64_C is defined when using the AMD64 assembly code because the C key            scheduling is sued in this case.DLL_EXPORT  must be defined to generate the DLL version of the code and            to run tests on itDLL_IMPORT  must be defined to use the DLL version of the code in an            application programDirectories the paths for the various directories for test vector input and            output have to be set in aestst.hVIA ACE     see the via_ace.txt for this itemStatic      The static libraries are named:Libraries                aes_lib_generic_c.lib                aes_lib_asm_x86_v1c.lib                aes_lib_asm_x86_v2.lib                aes_lib_asm_x86_v2c.lib                aes_lib_asm_amd64_c.lib            and placed in one of the the directories:                lib\win32\release\                lib\win32\debug\                lib\x64\release\                lib\x64\debug\            in the aes root directory depending on the platform(win32 or            x64) and the build (release or debug). After any of these is            built it is then copied into aes.lib, which is the library            that is subsequently used for testing. Hence testing is for            the last static library built.Dynamic     The static libraries are named:Libraries                aes_lib_generic_c.dll                aes_lib_asm_x86_v1c.dll                aes_lib_asm_x86_v2.dll                aes_lib_asm_x86_v2c.dll                aes_lib_asm_amd64_c.dll            and placed in one of the the directories:                dll\win32\release\                dll\win32\debug\                dll\x64\release\                dll\x64\debug\            in the aes root directory depending on the platform(win32 or            x64) and the build (release or debug).  Each DLL library:                aes_<ext>.dll            has three associated files:                aes_dll_<ext>.lib   the library file for implicit linking                aes_dll_<ext>.exp   the exports file                aes_dll_<ext>.pdb   the symbol file            After any DLL is built it and its three related files are then            copied into aes.lib, aes.lib, aes,exp and aes.pdb, which are            the libraries used for testing.  Hence testing is for the last            static library or DLL built.E. Testing----------These tests require that the test vector files are placed in the 'testvals' subdirectory. If the AES Algorithm Validation Suite tests will be use3d thenthe *.fax files need to be put in the 'testvals\fax' subdirectory.  This iscovered in more detail below.The projects test_dll and time_dll are used to test and time the last DLLbuilt.  These use the files:    test_dll:       Win32 (x64 for the C and AMD64 versions)        headers:    aes.h, aescpp.h, brg_types.h, aesaux.h and aestst.h        C source:   aesaux.c, aesrav.c        defines:    DLL_IMPORT    time_dll:       Win32 (x64 for the C and AMD64 versions)        headers:    aes.h, aescpp.h, brg_types.h, aesaux.h aestst.h and rdtsc.h        C source:   aesaux.c, aestmr.c        defines:    DLL_IMPORTand link to the DLL using explicit linking. However, if the lib file associatedwith the DLL is linked into this project and the symbol DYNAMIC_LINK in aestst.his left undefined, then implicit linking will be usedThe projects test_lib and time_lib are used to test and time the last static LIBbuilt. They use the files:    test_lib:       Win32 (x64 for the C and AMD64 versions)        headers:    aes.h, aescpp.h, brg_types.h, aesaux.h and aestst.h        C source:   aesaux.c, aesrav.c        defines:    time_lib:       Win32 (x64 for the C and AMD64 versions)        headers:    aes.h, aescpp.h, brg_types.h, aesaux.h, aestst.h and rdtsc.h        C source:   aesaux.c, aestmr.c        defines:and link to the last static library built.The above test take command line arguments that determine which test are runas follows:    test_lib /t:[knec] /k:[468]    test_dll /t:[knec] /k:[468]where the symbols in square brackets can be used in any combination (withoutthe brackets) and have the following meanings:        /t:[knec]   selects which tests are used        /k:[468]    selects the key lengths used        /c          compares output with reference (see later)        k: generate ECB Known Answer Test files        n: generate ECB Known Answer Test files (new)        e: generate ECB Monte Carlo Test files        c: generate CBC Monte Carlo Test filesand the characters giving the lengths are digits representing the lengths in32-bit units.\n\n");The project test_modes tests the AES modes.  It uses the files:    test_modes:     Win32 or x64        headers:    aes.h, aescpp.h, brg_types.h, aesaux,h and aestst.h        C source:   aesaux.c, modetest.c        defines:    none for static library test, DLL_IMPORT for DLL testwhich again links to the last library built.F. Other Applications---------------------These are:    gen_tests       builds the test_vector files. The commad line is                        gen_tests /t:knec /k:468 /c                    as described earlier                        test_aes_avs    run the AES Algorithm Validation Suite tests for                    ECB, CBC, CFB and OFB modes    gen_tables      builds a simple version of aes_tab.c (in aestab2.c)                    for compilers that cannot handle the normal version    aes_example     provides an example of AES useThese applications are linked to the last static library built or, ifDLL_IMPORT is defined during compilation, to the last DLL built.G. Use of the VIA ACE Cryptography Engine-----------------------------------------The use of the code with the VIA ACE cryptography engine in described in thefile via_ace.txt. In outline aes_modes.c is used and USE_VIA_ACE_IF_PRESENTis defined either in section 2 of aesopt.h or as a compilation option in VisualStudio. If in addition ASSUME_VIA_ACE_PRESENT is also defined then all normalAES code will be removed if not needed to support VIA ACE use.  If VIA ACEsupport is needed and AES assembler is being used only the ASM_X86_V1C andASM_X86_V2C versions should be used since ASM_X86_V2 and ASM_AMD64 do notsupport the VIA ACE engine.H. The AES Test Vector Files----------------------------These files fall in the following groups (where <nn> is a two digitnumber):1. ecbvk<nn>.txt  ECB vectors with variable key2. ecbvt<nn>.txt  ECB vectors with variable text3. ecbnk<nn>.txt  new ECB vectors with variable key4. ecbnt<nn>.txt  new ECB vectors with variable text5. ecbme<nn>.txt  ECB monte carlo encryption test vectors6. ecbmd<nn>.txt  ECB monte carlo decryption test vectors7. cbcme<nn>.txt  CBC monte carlo encryption test vectors8. cbcmd<nn>.txt  CBC monte carlo decryption test vectorsThe first digit of the numeric suffix on the filename gives the block sizein 32 bit units and the second numeric digit gives the key size. For example,the file ecbvk44.txt provides the test vectors for ECB encryption with a 128bit block size and a 128 bit key size. The test routines expect to find thesefiles in the 'testvals' subdirectory within the aes root directory. The'outvals' subdirectory is used for outputs that are compared with the filesin 'testvals'. Note that the monte carlo test vectors are the result ofapplying AES iteratively 10000 times, not just once.The AES Algorithm Validation Suite tests can be run for ECB, CBC, CFB and OFB modes (CFB1 and CFB8 are not implemented).  The test routine uses the *.fax test files, which should be placed in the 'testvals\fax' subdirectory.I. The Basic AES Calling Interface----------------------------------The basic AES code keeps its state in a context, there being different contexts for encryption and decryption:    aes_encrypt_ctx    aes_decrypt_ctx    The AES code is initialised with the callaes_init(void)although this is only essential if the option to generate the AES tables at run-time has been set in the options (i.e.fixed tables are not being used).    The AES encryption key is set by one of the calls:     aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1])    aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1])    aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1])or by:    aes_encrypt_key(const unsigned char *key, int key_len,                                                 aes_encrypt_ctx cx[1])where the key length is set by 'key_len', which can be the length in bits or bytes.  Similarly, the AES decryption key is set by one of:    aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1])    aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1])    aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1])or by:    aes_decrypt_key(const unsigned char *key, int key_len,                                                 aes_decrypt_ctx cx[1]) Encryption and decryption for a single 16 byte block is then achieved using:    aes_encrypt(const unsigned char *in, unsigned char *out,                                             const aes_encrypt_ctx cx[1])    aes_decrypt(const unsigned char *in, unsigned char *out,                                             const aes_decrypt_ctx cx[1])                                            The above subroutines return a value of EXIT_SUCCESS or EXIT_FAILURE depending on whether the operation succeeded or failed. J. The Calling Interface for the AES Modes------------------------------------------The subroutines for the AES modes, ECB, CBC, CFB, OFB and CTR, each processblocks of variable length and can also be called several times to complete single mode operations incrementally on long messages (or those messages,not all of which are available at the same time).  The calls:    aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,                    int len, const aes_encrypt_ctx cx[1])    aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,                    int len, const aes_decrypt_ctx cx[1])for ECB operations and those for CBC:    aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,                    int len, unsigned char *iv, const aes_encrypt_ctx cx[1])    aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,                    int len, unsigned char *iv, const aes_decrypt_ctx cx[1]) can only process blocks whose lengths are multiples of 16 bytes but the calls for CFB, OFB and CTR mode operations:    aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,                    int len, unsigned char *iv, aes_encrypt_ctx cx[1])    aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,                    int len, unsigned char *iv, aes_encrypt_ctx cx[1])    aes_ofb_encrypt(const unsigned char *ibuf, unsigned char *obuf,                    int len, unsigned char *iv, aes_encrypt_ctx cx[1])    aes_ofb_decrypt(const unsigned char *ibuf, unsigned char *obuf,                    int len, unsigned char *iv, aes_encrypt_ctx cx[1])    aes_ctr_encrypt(const unsigned char *ibuf, unsigned char *obuf,            int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1])    aes_ctr_decrypt(const unsigned char *ibuf, unsigned char *obuf,            int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1])can process blocks of any length.  Note also that CFB, OFB and CTR mode calls onlyuse AES encryption contexts even during decryption operations.The calls CTR mode operations use a buffer (cbuf) which holds the counter valuetogether with a function parameter:    void cbuf_inc(unsigned char *cbuf);that is ued to update the counter value after each 16 byte AES operation. The counter buffer is updated appropriately to allow for incremental operations.Please note the following IMPORTANT points about the AES mode subroutines:    1. All modes are reset when a new AES key is set.        2. Incremental calls to the different modes cannot        be mixed. If a change of mode is needed a new        key must be set or a reset must be issued (see        below).           3. For modes with IVs, the IV value is an inpu AND       an ouput since it is updated after each call to        the value needed for any subsequent incremental       call(s). If the mode is reset, the IV hence has       to be set (or reset) as well.           4. ECB operations must be multiples of 16 bytes       but do not need to be reset for new operations.           5. CBC operations must also be multiples of 16        bytes and are reset for a new operation by        setting the IV.           6. CFB, OFB and CTR mode must be reset by setting        a new IV value AND by calling:                  aes_mode_reset(aes_encrypt_ctx cx[1])                  For CTR mode the cbuf value also has to be reset.           7. CFB, OFB and CTR modes only use AES encryption        operations and contexts and do not need AES       decrytpion operations.           8. AES keys remain valid across resets and changes       of mode (but encryption and decryption keys must        both be set if they are needed).            Brian Gladman  22/07/2008   
原创粉丝点击