├── LICENSE ├── README.md ├── examples ├── aes.c ├── aes.h ├── aes.tgz ├── aes_asm.png ├── aes_cfg.png ├── homeomorphism.gif ├── homeomorphism_1.gif ├── homeomorphism_2.gif ├── mines.c ├── mines.tgz ├── mines_asm.png └── mines_cfg.png └── reductio.py /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Battelle Memorial Institute 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## _reductio_ [ad absurdum] 2 | 3 | an exploration of code homeomorphism 4 | : all programs can be reduced to the same instruction stream. 5 | 6 | github.com/xoreaxeaxeax/reductio // domas // @xoreaxeaxeax 7 | 8 | AES | Minesweeper 9 | :------------------------------------:|:------------------------------------: 10 | ![aes cfg](examples/aes_cfg.png) | ![mines cfg](examples/mines_cfg.png) 11 | 12 | 13 | ## Concept 14 | 15 | In the mathematical field of topology, two topological spaces are said to be 16 | *homeomorphic* if (roughly speaking) one can be transformed into the other 17 | through continuous deformation: 18 | 19 | ![homeomorphism](examples/homeomorphism.gif) 20 | 21 | Equivalently, two spaces are homeomorphic when both can be reduced to an 22 | identical, topologically equivalent space: 23 | 24 | ![homeomorphism](examples/homeomorphism_1.gif) ![homeomorphism](examples/homeomorphism_2.gif) 25 | 26 | _reductio_ imagines a similar concept for computer code: performing a series of 27 | transformations on entirely different programs, to induce an equivalence in 28 | instruction streams. 29 | 30 | 31 | ## Overview 32 | 33 | r.a.a. reduces all C programs to identical instruction streams; that is, the 34 | instructions executed by the processor become the same for every program. The 35 | demonstration uses C and x86, but is not unique to either of these - the concept 36 | is easily adapted to most languages and architectures. 37 | 38 | 39 | ## Usage 40 | 41 | ``` 42 | python reductio.py example.c 43 | ``` 44 | 45 | 46 | ## Examples 47 | 48 | The basic effects of the process can be seen in [examples](examples/), which 49 | contains the reduced versions of two programs: AES and Minesweeper. The 50 | disassembly of each is shown below. 51 | 52 | AES | Minesweeper 53 | :------------------------------------:|:------------------------------------: 54 | ![aes asm](examples/aes_asm.png) | ![mines asm](examples/mines_asm.png) 55 | 56 | The instructions execute in a continuous loop, and are the same for every 57 | program. The final jmp performs the loop, and, when necessary, branches to 58 | shared libraries; for example, if a program calls 'malloc', malloc is executed 59 | through the jmp. This is only necessary when programs are linked to non-reduced 60 | code; if all code is run through the reduction, the dynamic jmp can be replace 61 | with a constant loop back to the beginning of the program. 62 | 63 | 64 | ## Notes 65 | 66 | * r.a.a. reduces all code to the same instruction stream. Note that this is 67 | distinct from, for example, an emulator, wherein a single set of 68 | instructions can run multiple programs, but the sequence of instructions 69 | differs depending on what program is being emulated. In r.a.a., rather, a 70 | processor performs the exact same steps for every program, yet from this is 71 | able to produce any possible result. 72 | 73 | * r.a.a. allows you to link to other, non-reduced code; for example, you 74 | can link to the standard C libraries without recompiling them. Naturally, 75 | if you do this, the instruction streams will diverge in the non-reduced 76 | libraries. 77 | 78 | * The reduction may be limited by the constraints of the OS - for example, if 79 | the only provided way to perform I/O is a syscall, the instruction stream 80 | must diverge at the syscall. However, assuming the OS provides sufficient 81 | MMIO capabilities, the reduction premise holds. 82 | 83 | * r.a.a. leverages the M/o/Vfuscator compiler as a first pass, to simplify the 84 | set of instructions we must work with. To install the M/o/Vfuscator, 85 | 86 | ``` 87 | git clone https://github.com/xoreaxeaxeax/movfuscator 88 | cd movfuscator 89 | ./build.sh 90 | sudo ./install.sh 91 | ``` 92 | 93 | * The reduction may consume significant amounts of memory. Ensure you have an 94 | adequate swap file in place to prevent crashes during the reduction process. 95 | 96 | 97 | ## References 98 | 99 | The technique is outlined in detail in the [Shakacon 100 | presentation](https://www.youtube.com/watch?v=NmWwRmvjAE8). 101 | 102 | 103 | ## Author 104 | 105 | reductio is a proof-of-concept from Christopher Domas 106 | ([@xoreaxeaxeax](https://twitter.com/xoreaxeaxeax)). 107 | -------------------------------------------------------------------------------- /examples/aes.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: aes.c 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: This code is the implementation of the AES algorithm and 7 | the CTR, CBC, and CCM modes of operation it can be used in. 8 | AES is, specified by the NIST in in publication FIPS PUB 197, 9 | availible at: 10 | * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf . 11 | The CBC and CTR modes of operation are specified by 12 | NIST SP 800-38 A, available at: 13 | * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf . 14 | The CCM mode of operation is specified by NIST SP80-38 C, available at: 15 | * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf 16 | *********************************************************************/ 17 | 18 | /*************************** HEADER FILES ***************************/ 19 | #include 20 | #include 21 | #include "aes.h" 22 | 23 | #include 24 | 25 | /****************************** MACROS ******************************/ 26 | // The least significant byte of the word is rotated to the end. 27 | #define KE_ROTWORD(x) (((x) << 8) | ((x) >> 24)) 28 | 29 | #define TRUE 1 30 | #define FALSE 0 31 | 32 | /**************************** DATA TYPES ****************************/ 33 | #define AES_128_ROUNDS 10 34 | #define AES_192_ROUNDS 12 35 | #define AES_256_ROUNDS 14 36 | 37 | /*********************** FUNCTION DECLARATIONS **********************/ 38 | void ccm_prepare_first_ctr_blk(BYTE counter[], const BYTE nonce[], int nonce_len, int payload_len_store_size); 39 | void ccm_prepare_first_format_blk(BYTE buf[], int assoc_len, int payload_len, int payload_len_store_size, int mac_len, const BYTE nonce[], int nonce_len); 40 | void ccm_format_assoc_data(BYTE buf[], int *end_of_buf, const BYTE assoc[], int assoc_len); 41 | void ccm_format_payload_data(BYTE buf[], int *end_of_buf, const BYTE payload[], int payload_len); 42 | 43 | /**************************** VARIABLES *****************************/ 44 | // This is the specified AES SBox. To look up a substitution value, put the first 45 | // nibble in the first index (row) and the second nibble in the second index (column). 46 | static const BYTE aes_sbox[16][16] = { 47 | {0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76}, 48 | {0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0}, 49 | {0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15}, 50 | {0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75}, 51 | {0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84}, 52 | {0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF}, 53 | {0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8}, 54 | {0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2}, 55 | {0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73}, 56 | {0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB}, 57 | {0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79}, 58 | {0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08}, 59 | {0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A}, 60 | {0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E}, 61 | {0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF}, 62 | {0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16} 63 | }; 64 | 65 | static const BYTE aes_invsbox[16][16] = { 66 | {0x52,0x09,0x6A,0xD5,0x30,0x36,0xA5,0x38,0xBF,0x40,0xA3,0x9E,0x81,0xF3,0xD7,0xFB}, 67 | {0x7C,0xE3,0x39,0x82,0x9B,0x2F,0xFF,0x87,0x34,0x8E,0x43,0x44,0xC4,0xDE,0xE9,0xCB}, 68 | {0x54,0x7B,0x94,0x32,0xA6,0xC2,0x23,0x3D,0xEE,0x4C,0x95,0x0B,0x42,0xFA,0xC3,0x4E}, 69 | {0x08,0x2E,0xA1,0x66,0x28,0xD9,0x24,0xB2,0x76,0x5B,0xA2,0x49,0x6D,0x8B,0xD1,0x25}, 70 | {0x72,0xF8,0xF6,0x64,0x86,0x68,0x98,0x16,0xD4,0xA4,0x5C,0xCC,0x5D,0x65,0xB6,0x92}, 71 | {0x6C,0x70,0x48,0x50,0xFD,0xED,0xB9,0xDA,0x5E,0x15,0x46,0x57,0xA7,0x8D,0x9D,0x84}, 72 | {0x90,0xD8,0xAB,0x00,0x8C,0xBC,0xD3,0x0A,0xF7,0xE4,0x58,0x05,0xB8,0xB3,0x45,0x06}, 73 | {0xD0,0x2C,0x1E,0x8F,0xCA,0x3F,0x0F,0x02,0xC1,0xAF,0xBD,0x03,0x01,0x13,0x8A,0x6B}, 74 | {0x3A,0x91,0x11,0x41,0x4F,0x67,0xDC,0xEA,0x97,0xF2,0xCF,0xCE,0xF0,0xB4,0xE6,0x73}, 75 | {0x96,0xAC,0x74,0x22,0xE7,0xAD,0x35,0x85,0xE2,0xF9,0x37,0xE8,0x1C,0x75,0xDF,0x6E}, 76 | {0x47,0xF1,0x1A,0x71,0x1D,0x29,0xC5,0x89,0x6F,0xB7,0x62,0x0E,0xAA,0x18,0xBE,0x1B}, 77 | {0xFC,0x56,0x3E,0x4B,0xC6,0xD2,0x79,0x20,0x9A,0xDB,0xC0,0xFE,0x78,0xCD,0x5A,0xF4}, 78 | {0x1F,0xDD,0xA8,0x33,0x88,0x07,0xC7,0x31,0xB1,0x12,0x10,0x59,0x27,0x80,0xEC,0x5F}, 79 | {0x60,0x51,0x7F,0xA9,0x19,0xB5,0x4A,0x0D,0x2D,0xE5,0x7A,0x9F,0x93,0xC9,0x9C,0xEF}, 80 | {0xA0,0xE0,0x3B,0x4D,0xAE,0x2A,0xF5,0xB0,0xC8,0xEB,0xBB,0x3C,0x83,0x53,0x99,0x61}, 81 | {0x17,0x2B,0x04,0x7E,0xBA,0x77,0xD6,0x26,0xE1,0x69,0x14,0x63,0x55,0x21,0x0C,0x7D} 82 | }; 83 | 84 | // This table stores pre-calculated values for all possible GF(2^8) calculations.This 85 | // table is only used by the (Inv)MixColumns steps. 86 | // USAGE: The second index (column) is the coefficient of multiplication. Only 7 different 87 | // coefficients are used: 0x01, 0x02, 0x03, 0x09, 0x0b, 0x0d, 0x0e, but multiplication by 88 | // 1 is negligible leaving only 6 coefficients. Each column of the table is devoted to one 89 | // of these coefficients, in the ascending order of value, from values 0x00 to 0xFF. 90 | static const BYTE gf_mul[256][6] = { 91 | {0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x03,0x09,0x0b,0x0d,0x0e}, 92 | {0x04,0x06,0x12,0x16,0x1a,0x1c},{0x06,0x05,0x1b,0x1d,0x17,0x12}, 93 | {0x08,0x0c,0x24,0x2c,0x34,0x38},{0x0a,0x0f,0x2d,0x27,0x39,0x36}, 94 | {0x0c,0x0a,0x36,0x3a,0x2e,0x24},{0x0e,0x09,0x3f,0x31,0x23,0x2a}, 95 | {0x10,0x18,0x48,0x58,0x68,0x70},{0x12,0x1b,0x41,0x53,0x65,0x7e}, 96 | {0x14,0x1e,0x5a,0x4e,0x72,0x6c},{0x16,0x1d,0x53,0x45,0x7f,0x62}, 97 | {0x18,0x14,0x6c,0x74,0x5c,0x48},{0x1a,0x17,0x65,0x7f,0x51,0x46}, 98 | {0x1c,0x12,0x7e,0x62,0x46,0x54},{0x1e,0x11,0x77,0x69,0x4b,0x5a}, 99 | {0x20,0x30,0x90,0xb0,0xd0,0xe0},{0x22,0x33,0x99,0xbb,0xdd,0xee}, 100 | {0x24,0x36,0x82,0xa6,0xca,0xfc},{0x26,0x35,0x8b,0xad,0xc7,0xf2}, 101 | {0x28,0x3c,0xb4,0x9c,0xe4,0xd8},{0x2a,0x3f,0xbd,0x97,0xe9,0xd6}, 102 | {0x2c,0x3a,0xa6,0x8a,0xfe,0xc4},{0x2e,0x39,0xaf,0x81,0xf3,0xca}, 103 | {0x30,0x28,0xd8,0xe8,0xb8,0x90},{0x32,0x2b,0xd1,0xe3,0xb5,0x9e}, 104 | {0x34,0x2e,0xca,0xfe,0xa2,0x8c},{0x36,0x2d,0xc3,0xf5,0xaf,0x82}, 105 | {0x38,0x24,0xfc,0xc4,0x8c,0xa8},{0x3a,0x27,0xf5,0xcf,0x81,0xa6}, 106 | {0x3c,0x22,0xee,0xd2,0x96,0xb4},{0x3e,0x21,0xe7,0xd9,0x9b,0xba}, 107 | {0x40,0x60,0x3b,0x7b,0xbb,0xdb},{0x42,0x63,0x32,0x70,0xb6,0xd5}, 108 | {0x44,0x66,0x29,0x6d,0xa1,0xc7},{0x46,0x65,0x20,0x66,0xac,0xc9}, 109 | {0x48,0x6c,0x1f,0x57,0x8f,0xe3},{0x4a,0x6f,0x16,0x5c,0x82,0xed}, 110 | {0x4c,0x6a,0x0d,0x41,0x95,0xff},{0x4e,0x69,0x04,0x4a,0x98,0xf1}, 111 | {0x50,0x78,0x73,0x23,0xd3,0xab},{0x52,0x7b,0x7a,0x28,0xde,0xa5}, 112 | {0x54,0x7e,0x61,0x35,0xc9,0xb7},{0x56,0x7d,0x68,0x3e,0xc4,0xb9}, 113 | {0x58,0x74,0x57,0x0f,0xe7,0x93},{0x5a,0x77,0x5e,0x04,0xea,0x9d}, 114 | {0x5c,0x72,0x45,0x19,0xfd,0x8f},{0x5e,0x71,0x4c,0x12,0xf0,0x81}, 115 | {0x60,0x50,0xab,0xcb,0x6b,0x3b},{0x62,0x53,0xa2,0xc0,0x66,0x35}, 116 | {0x64,0x56,0xb9,0xdd,0x71,0x27},{0x66,0x55,0xb0,0xd6,0x7c,0x29}, 117 | {0x68,0x5c,0x8f,0xe7,0x5f,0x03},{0x6a,0x5f,0x86,0xec,0x52,0x0d}, 118 | {0x6c,0x5a,0x9d,0xf1,0x45,0x1f},{0x6e,0x59,0x94,0xfa,0x48,0x11}, 119 | {0x70,0x48,0xe3,0x93,0x03,0x4b},{0x72,0x4b,0xea,0x98,0x0e,0x45}, 120 | {0x74,0x4e,0xf1,0x85,0x19,0x57},{0x76,0x4d,0xf8,0x8e,0x14,0x59}, 121 | {0x78,0x44,0xc7,0xbf,0x37,0x73},{0x7a,0x47,0xce,0xb4,0x3a,0x7d}, 122 | {0x7c,0x42,0xd5,0xa9,0x2d,0x6f},{0x7e,0x41,0xdc,0xa2,0x20,0x61}, 123 | {0x80,0xc0,0x76,0xf6,0x6d,0xad},{0x82,0xc3,0x7f,0xfd,0x60,0xa3}, 124 | {0x84,0xc6,0x64,0xe0,0x77,0xb1},{0x86,0xc5,0x6d,0xeb,0x7a,0xbf}, 125 | {0x88,0xcc,0x52,0xda,0x59,0x95},{0x8a,0xcf,0x5b,0xd1,0x54,0x9b}, 126 | {0x8c,0xca,0x40,0xcc,0x43,0x89},{0x8e,0xc9,0x49,0xc7,0x4e,0x87}, 127 | {0x90,0xd8,0x3e,0xae,0x05,0xdd},{0x92,0xdb,0x37,0xa5,0x08,0xd3}, 128 | {0x94,0xde,0x2c,0xb8,0x1f,0xc1},{0x96,0xdd,0x25,0xb3,0x12,0xcf}, 129 | {0x98,0xd4,0x1a,0x82,0x31,0xe5},{0x9a,0xd7,0x13,0x89,0x3c,0xeb}, 130 | {0x9c,0xd2,0x08,0x94,0x2b,0xf9},{0x9e,0xd1,0x01,0x9f,0x26,0xf7}, 131 | {0xa0,0xf0,0xe6,0x46,0xbd,0x4d},{0xa2,0xf3,0xef,0x4d,0xb0,0x43}, 132 | {0xa4,0xf6,0xf4,0x50,0xa7,0x51},{0xa6,0xf5,0xfd,0x5b,0xaa,0x5f}, 133 | {0xa8,0xfc,0xc2,0x6a,0x89,0x75},{0xaa,0xff,0xcb,0x61,0x84,0x7b}, 134 | {0xac,0xfa,0xd0,0x7c,0x93,0x69},{0xae,0xf9,0xd9,0x77,0x9e,0x67}, 135 | {0xb0,0xe8,0xae,0x1e,0xd5,0x3d},{0xb2,0xeb,0xa7,0x15,0xd8,0x33}, 136 | {0xb4,0xee,0xbc,0x08,0xcf,0x21},{0xb6,0xed,0xb5,0x03,0xc2,0x2f}, 137 | {0xb8,0xe4,0x8a,0x32,0xe1,0x05},{0xba,0xe7,0x83,0x39,0xec,0x0b}, 138 | {0xbc,0xe2,0x98,0x24,0xfb,0x19},{0xbe,0xe1,0x91,0x2f,0xf6,0x17}, 139 | {0xc0,0xa0,0x4d,0x8d,0xd6,0x76},{0xc2,0xa3,0x44,0x86,0xdb,0x78}, 140 | {0xc4,0xa6,0x5f,0x9b,0xcc,0x6a},{0xc6,0xa5,0x56,0x90,0xc1,0x64}, 141 | {0xc8,0xac,0x69,0xa1,0xe2,0x4e},{0xca,0xaf,0x60,0xaa,0xef,0x40}, 142 | {0xcc,0xaa,0x7b,0xb7,0xf8,0x52},{0xce,0xa9,0x72,0xbc,0xf5,0x5c}, 143 | {0xd0,0xb8,0x05,0xd5,0xbe,0x06},{0xd2,0xbb,0x0c,0xde,0xb3,0x08}, 144 | {0xd4,0xbe,0x17,0xc3,0xa4,0x1a},{0xd6,0xbd,0x1e,0xc8,0xa9,0x14}, 145 | {0xd8,0xb4,0x21,0xf9,0x8a,0x3e},{0xda,0xb7,0x28,0xf2,0x87,0x30}, 146 | {0xdc,0xb2,0x33,0xef,0x90,0x22},{0xde,0xb1,0x3a,0xe4,0x9d,0x2c}, 147 | {0xe0,0x90,0xdd,0x3d,0x06,0x96},{0xe2,0x93,0xd4,0x36,0x0b,0x98}, 148 | {0xe4,0x96,0xcf,0x2b,0x1c,0x8a},{0xe6,0x95,0xc6,0x20,0x11,0x84}, 149 | {0xe8,0x9c,0xf9,0x11,0x32,0xae},{0xea,0x9f,0xf0,0x1a,0x3f,0xa0}, 150 | {0xec,0x9a,0xeb,0x07,0x28,0xb2},{0xee,0x99,0xe2,0x0c,0x25,0xbc}, 151 | {0xf0,0x88,0x95,0x65,0x6e,0xe6},{0xf2,0x8b,0x9c,0x6e,0x63,0xe8}, 152 | {0xf4,0x8e,0x87,0x73,0x74,0xfa},{0xf6,0x8d,0x8e,0x78,0x79,0xf4}, 153 | {0xf8,0x84,0xb1,0x49,0x5a,0xde},{0xfa,0x87,0xb8,0x42,0x57,0xd0}, 154 | {0xfc,0x82,0xa3,0x5f,0x40,0xc2},{0xfe,0x81,0xaa,0x54,0x4d,0xcc}, 155 | {0x1b,0x9b,0xec,0xf7,0xda,0x41},{0x19,0x98,0xe5,0xfc,0xd7,0x4f}, 156 | {0x1f,0x9d,0xfe,0xe1,0xc0,0x5d},{0x1d,0x9e,0xf7,0xea,0xcd,0x53}, 157 | {0x13,0x97,0xc8,0xdb,0xee,0x79},{0x11,0x94,0xc1,0xd0,0xe3,0x77}, 158 | {0x17,0x91,0xda,0xcd,0xf4,0x65},{0x15,0x92,0xd3,0xc6,0xf9,0x6b}, 159 | {0x0b,0x83,0xa4,0xaf,0xb2,0x31},{0x09,0x80,0xad,0xa4,0xbf,0x3f}, 160 | {0x0f,0x85,0xb6,0xb9,0xa8,0x2d},{0x0d,0x86,0xbf,0xb2,0xa5,0x23}, 161 | {0x03,0x8f,0x80,0x83,0x86,0x09},{0x01,0x8c,0x89,0x88,0x8b,0x07}, 162 | {0x07,0x89,0x92,0x95,0x9c,0x15},{0x05,0x8a,0x9b,0x9e,0x91,0x1b}, 163 | {0x3b,0xab,0x7c,0x47,0x0a,0xa1},{0x39,0xa8,0x75,0x4c,0x07,0xaf}, 164 | {0x3f,0xad,0x6e,0x51,0x10,0xbd},{0x3d,0xae,0x67,0x5a,0x1d,0xb3}, 165 | {0x33,0xa7,0x58,0x6b,0x3e,0x99},{0x31,0xa4,0x51,0x60,0x33,0x97}, 166 | {0x37,0xa1,0x4a,0x7d,0x24,0x85},{0x35,0xa2,0x43,0x76,0x29,0x8b}, 167 | {0x2b,0xb3,0x34,0x1f,0x62,0xd1},{0x29,0xb0,0x3d,0x14,0x6f,0xdf}, 168 | {0x2f,0xb5,0x26,0x09,0x78,0xcd},{0x2d,0xb6,0x2f,0x02,0x75,0xc3}, 169 | {0x23,0xbf,0x10,0x33,0x56,0xe9},{0x21,0xbc,0x19,0x38,0x5b,0xe7}, 170 | {0x27,0xb9,0x02,0x25,0x4c,0xf5},{0x25,0xba,0x0b,0x2e,0x41,0xfb}, 171 | {0x5b,0xfb,0xd7,0x8c,0x61,0x9a},{0x59,0xf8,0xde,0x87,0x6c,0x94}, 172 | {0x5f,0xfd,0xc5,0x9a,0x7b,0x86},{0x5d,0xfe,0xcc,0x91,0x76,0x88}, 173 | {0x53,0xf7,0xf3,0xa0,0x55,0xa2},{0x51,0xf4,0xfa,0xab,0x58,0xac}, 174 | {0x57,0xf1,0xe1,0xb6,0x4f,0xbe},{0x55,0xf2,0xe8,0xbd,0x42,0xb0}, 175 | {0x4b,0xe3,0x9f,0xd4,0x09,0xea},{0x49,0xe0,0x96,0xdf,0x04,0xe4}, 176 | {0x4f,0xe5,0x8d,0xc2,0x13,0xf6},{0x4d,0xe6,0x84,0xc9,0x1e,0xf8}, 177 | {0x43,0xef,0xbb,0xf8,0x3d,0xd2},{0x41,0xec,0xb2,0xf3,0x30,0xdc}, 178 | {0x47,0xe9,0xa9,0xee,0x27,0xce},{0x45,0xea,0xa0,0xe5,0x2a,0xc0}, 179 | {0x7b,0xcb,0x47,0x3c,0xb1,0x7a},{0x79,0xc8,0x4e,0x37,0xbc,0x74}, 180 | {0x7f,0xcd,0x55,0x2a,0xab,0x66},{0x7d,0xce,0x5c,0x21,0xa6,0x68}, 181 | {0x73,0xc7,0x63,0x10,0x85,0x42},{0x71,0xc4,0x6a,0x1b,0x88,0x4c}, 182 | {0x77,0xc1,0x71,0x06,0x9f,0x5e},{0x75,0xc2,0x78,0x0d,0x92,0x50}, 183 | {0x6b,0xd3,0x0f,0x64,0xd9,0x0a},{0x69,0xd0,0x06,0x6f,0xd4,0x04}, 184 | {0x6f,0xd5,0x1d,0x72,0xc3,0x16},{0x6d,0xd6,0x14,0x79,0xce,0x18}, 185 | {0x63,0xdf,0x2b,0x48,0xed,0x32},{0x61,0xdc,0x22,0x43,0xe0,0x3c}, 186 | {0x67,0xd9,0x39,0x5e,0xf7,0x2e},{0x65,0xda,0x30,0x55,0xfa,0x20}, 187 | {0x9b,0x5b,0x9a,0x01,0xb7,0xec},{0x99,0x58,0x93,0x0a,0xba,0xe2}, 188 | {0x9f,0x5d,0x88,0x17,0xad,0xf0},{0x9d,0x5e,0x81,0x1c,0xa0,0xfe}, 189 | {0x93,0x57,0xbe,0x2d,0x83,0xd4},{0x91,0x54,0xb7,0x26,0x8e,0xda}, 190 | {0x97,0x51,0xac,0x3b,0x99,0xc8},{0x95,0x52,0xa5,0x30,0x94,0xc6}, 191 | {0x8b,0x43,0xd2,0x59,0xdf,0x9c},{0x89,0x40,0xdb,0x52,0xd2,0x92}, 192 | {0x8f,0x45,0xc0,0x4f,0xc5,0x80},{0x8d,0x46,0xc9,0x44,0xc8,0x8e}, 193 | {0x83,0x4f,0xf6,0x75,0xeb,0xa4},{0x81,0x4c,0xff,0x7e,0xe6,0xaa}, 194 | {0x87,0x49,0xe4,0x63,0xf1,0xb8},{0x85,0x4a,0xed,0x68,0xfc,0xb6}, 195 | {0xbb,0x6b,0x0a,0xb1,0x67,0x0c},{0xb9,0x68,0x03,0xba,0x6a,0x02}, 196 | {0xbf,0x6d,0x18,0xa7,0x7d,0x10},{0xbd,0x6e,0x11,0xac,0x70,0x1e}, 197 | {0xb3,0x67,0x2e,0x9d,0x53,0x34},{0xb1,0x64,0x27,0x96,0x5e,0x3a}, 198 | {0xb7,0x61,0x3c,0x8b,0x49,0x28},{0xb5,0x62,0x35,0x80,0x44,0x26}, 199 | {0xab,0x73,0x42,0xe9,0x0f,0x7c},{0xa9,0x70,0x4b,0xe2,0x02,0x72}, 200 | {0xaf,0x75,0x50,0xff,0x15,0x60},{0xad,0x76,0x59,0xf4,0x18,0x6e}, 201 | {0xa3,0x7f,0x66,0xc5,0x3b,0x44},{0xa1,0x7c,0x6f,0xce,0x36,0x4a}, 202 | {0xa7,0x79,0x74,0xd3,0x21,0x58},{0xa5,0x7a,0x7d,0xd8,0x2c,0x56}, 203 | {0xdb,0x3b,0xa1,0x7a,0x0c,0x37},{0xd9,0x38,0xa8,0x71,0x01,0x39}, 204 | {0xdf,0x3d,0xb3,0x6c,0x16,0x2b},{0xdd,0x3e,0xba,0x67,0x1b,0x25}, 205 | {0xd3,0x37,0x85,0x56,0x38,0x0f},{0xd1,0x34,0x8c,0x5d,0x35,0x01}, 206 | {0xd7,0x31,0x97,0x40,0x22,0x13},{0xd5,0x32,0x9e,0x4b,0x2f,0x1d}, 207 | {0xcb,0x23,0xe9,0x22,0x64,0x47},{0xc9,0x20,0xe0,0x29,0x69,0x49}, 208 | {0xcf,0x25,0xfb,0x34,0x7e,0x5b},{0xcd,0x26,0xf2,0x3f,0x73,0x55}, 209 | {0xc3,0x2f,0xcd,0x0e,0x50,0x7f},{0xc1,0x2c,0xc4,0x05,0x5d,0x71}, 210 | {0xc7,0x29,0xdf,0x18,0x4a,0x63},{0xc5,0x2a,0xd6,0x13,0x47,0x6d}, 211 | {0xfb,0x0b,0x31,0xca,0xdc,0xd7},{0xf9,0x08,0x38,0xc1,0xd1,0xd9}, 212 | {0xff,0x0d,0x23,0xdc,0xc6,0xcb},{0xfd,0x0e,0x2a,0xd7,0xcb,0xc5}, 213 | {0xf3,0x07,0x15,0xe6,0xe8,0xef},{0xf1,0x04,0x1c,0xed,0xe5,0xe1}, 214 | {0xf7,0x01,0x07,0xf0,0xf2,0xf3},{0xf5,0x02,0x0e,0xfb,0xff,0xfd}, 215 | {0xeb,0x13,0x79,0x92,0xb4,0xa7},{0xe9,0x10,0x70,0x99,0xb9,0xa9}, 216 | {0xef,0x15,0x6b,0x84,0xae,0xbb},{0xed,0x16,0x62,0x8f,0xa3,0xb5}, 217 | {0xe3,0x1f,0x5d,0xbe,0x80,0x9f},{0xe1,0x1c,0x54,0xb5,0x8d,0x91}, 218 | {0xe7,0x19,0x4f,0xa8,0x9a,0x83},{0xe5,0x1a,0x46,0xa3,0x97,0x8d} 219 | }; 220 | 221 | /*********************** FUNCTION DEFINITIONS ***********************/ 222 | // XORs the in and out buffers, storing the result in out. Length is in bytes. 223 | void xor_buf(const BYTE in[], BYTE out[], size_t len) 224 | { 225 | size_t idx; 226 | 227 | for (idx = 0; idx < len; idx++) 228 | out[idx] ^= in[idx]; 229 | } 230 | 231 | /******************* 232 | * AES - CBC 233 | *******************/ 234 | int aes_encrypt_cbc(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) 235 | { 236 | BYTE buf_in[AES_BLOCK_SIZE], buf_out[AES_BLOCK_SIZE], iv_buf[AES_BLOCK_SIZE]; 237 | int blocks, idx; 238 | 239 | if (in_len % AES_BLOCK_SIZE != 0) 240 | return(FALSE); 241 | 242 | blocks = in_len / AES_BLOCK_SIZE; 243 | 244 | memcpy(iv_buf, iv, AES_BLOCK_SIZE); 245 | 246 | for (idx = 0; idx < blocks; idx++) { 247 | memcpy(buf_in, &in[idx * AES_BLOCK_SIZE], AES_BLOCK_SIZE); 248 | xor_buf(iv_buf, buf_in, AES_BLOCK_SIZE); 249 | aes_encrypt(buf_in, buf_out, key, keysize); 250 | memcpy(&out[idx * AES_BLOCK_SIZE], buf_out, AES_BLOCK_SIZE); 251 | memcpy(iv_buf, buf_out, AES_BLOCK_SIZE); 252 | } 253 | 254 | return(TRUE); 255 | } 256 | 257 | int aes_encrypt_cbc_mac(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) 258 | { 259 | BYTE buf_in[AES_BLOCK_SIZE], buf_out[AES_BLOCK_SIZE], iv_buf[AES_BLOCK_SIZE]; 260 | int blocks, idx; 261 | 262 | if (in_len % AES_BLOCK_SIZE != 0) 263 | return(FALSE); 264 | 265 | blocks = in_len / AES_BLOCK_SIZE; 266 | 267 | memcpy(iv_buf, iv, AES_BLOCK_SIZE); 268 | 269 | for (idx = 0; idx < blocks; idx++) { 270 | memcpy(buf_in, &in[idx * AES_BLOCK_SIZE], AES_BLOCK_SIZE); 271 | xor_buf(iv_buf, buf_in, AES_BLOCK_SIZE); 272 | aes_encrypt(buf_in, buf_out, key, keysize); 273 | memcpy(iv_buf, buf_out, AES_BLOCK_SIZE); 274 | // Do not output all encrypted blocks. 275 | } 276 | 277 | memcpy(out, buf_out, AES_BLOCK_SIZE); // Only output the last block. 278 | 279 | return(TRUE); 280 | } 281 | 282 | int aes_decrypt_cbc(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) 283 | { 284 | BYTE buf_in[AES_BLOCK_SIZE], buf_out[AES_BLOCK_SIZE], iv_buf[AES_BLOCK_SIZE]; 285 | int blocks, idx; 286 | 287 | if (in_len % AES_BLOCK_SIZE != 0) 288 | return(FALSE); 289 | 290 | blocks = in_len / AES_BLOCK_SIZE; 291 | 292 | memcpy(iv_buf, iv, AES_BLOCK_SIZE); 293 | 294 | for (idx = 0; idx < blocks; idx++) { 295 | memcpy(buf_in, &in[idx * AES_BLOCK_SIZE], AES_BLOCK_SIZE); 296 | aes_decrypt(buf_in, buf_out, key, keysize); 297 | xor_buf(iv_buf, buf_out, AES_BLOCK_SIZE); 298 | memcpy(&out[idx * AES_BLOCK_SIZE], buf_out, AES_BLOCK_SIZE); 299 | memcpy(iv_buf, buf_in, AES_BLOCK_SIZE); 300 | } 301 | 302 | return(TRUE); 303 | } 304 | 305 | /******************* 306 | * AES - CTR 307 | *******************/ 308 | void increment_iv(BYTE iv[], int counter_size) 309 | { 310 | int idx; 311 | 312 | // Use counter_size bytes at the end of the IV as the big-endian integer to increment. 313 | for (idx = AES_BLOCK_SIZE - 1; idx >= AES_BLOCK_SIZE - counter_size; idx--) { 314 | iv[idx]++; 315 | if (iv[idx] != 0 || idx == AES_BLOCK_SIZE - counter_size) 316 | break; 317 | } 318 | } 319 | 320 | // Performs the encryption in-place, the input and output buffers may be the same. 321 | // Input may be an arbitrary length (in bytes). 322 | void aes_encrypt_ctr(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) 323 | { 324 | size_t idx = 0, last_block_length; 325 | BYTE iv_buf[AES_BLOCK_SIZE], out_buf[AES_BLOCK_SIZE]; 326 | 327 | if (in != out) 328 | memcpy(out, in, in_len); 329 | 330 | memcpy(iv_buf, iv, AES_BLOCK_SIZE); 331 | last_block_length = in_len - AES_BLOCK_SIZE; 332 | 333 | if (in_len > AES_BLOCK_SIZE) { 334 | for (idx = 0; idx < last_block_length; idx += AES_BLOCK_SIZE) { 335 | aes_encrypt(iv_buf, out_buf, key, keysize); 336 | xor_buf(out_buf, &out[idx], AES_BLOCK_SIZE); 337 | increment_iv(iv_buf, AES_BLOCK_SIZE); 338 | } 339 | } 340 | 341 | aes_encrypt(iv_buf, out_buf, key, keysize); 342 | xor_buf(out_buf, &out[idx], in_len - idx); // Use the Most Significant bytes. 343 | } 344 | 345 | void aes_decrypt_ctr(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) 346 | { 347 | // CTR encryption is its own inverse function. 348 | aes_encrypt_ctr(in, in_len, out, key, keysize, iv); 349 | } 350 | 351 | /******************* 352 | * AES - CCM 353 | *******************/ 354 | // out_len = payload_len + assoc_len 355 | int aes_encrypt_ccm(const BYTE payload[], WORD payload_len, const BYTE assoc[], unsigned short assoc_len, 356 | const BYTE nonce[], unsigned short nonce_len, BYTE out[], WORD *out_len, 357 | WORD mac_len, const BYTE key_str[], int keysize) 358 | { 359 | BYTE temp_iv[AES_BLOCK_SIZE], counter[AES_BLOCK_SIZE], mac[16], *buf; 360 | int end_of_buf, payload_len_store_size; 361 | WORD key[60]; 362 | 363 | if (mac_len != 4 && mac_len != 6 && mac_len != 8 && mac_len != 10 && 364 | mac_len != 12 && mac_len != 14 && mac_len != 16) 365 | return(FALSE); 366 | 367 | if (nonce_len < 7 || nonce_len > 13) 368 | return(FALSE); 369 | 370 | if (assoc_len > 32768 /* = 2^15 */) 371 | return(FALSE); 372 | 373 | buf = (BYTE*)malloc(payload_len + assoc_len + 48 /*Round both payload and associated data up a block size and add an extra block.*/); 374 | if (! buf) 375 | return(FALSE); 376 | 377 | // Prepare the key for usage. 378 | aes_key_setup(key_str, key, keysize); 379 | 380 | // Format the first block of the formatted data. 381 | payload_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; 382 | ccm_prepare_first_format_blk(buf, assoc_len, payload_len, payload_len_store_size, mac_len, nonce, nonce_len); 383 | end_of_buf = AES_BLOCK_SIZE; 384 | 385 | // Format the Associated Data, aka, assoc[]. 386 | ccm_format_assoc_data(buf, &end_of_buf, assoc, assoc_len); 387 | 388 | // Format the Payload, aka payload[]. 389 | ccm_format_payload_data(buf, &end_of_buf, payload, payload_len); 390 | 391 | // Create the first counter block. 392 | ccm_prepare_first_ctr_blk(counter, nonce, nonce_len, payload_len_store_size); 393 | 394 | // Perform the CBC operation with an IV of zeros on the formatted buffer to calculate the MAC. 395 | memset(temp_iv, 0, AES_BLOCK_SIZE); 396 | aes_encrypt_cbc_mac(buf, end_of_buf, mac, key, keysize, temp_iv); 397 | 398 | // Copy the Payload and MAC to the output buffer. 399 | memcpy(out, payload, payload_len); 400 | memcpy(&out[payload_len], mac, mac_len); 401 | 402 | // Encrypt the Payload with CTR mode with a counter starting at 1. 403 | memcpy(temp_iv, counter, AES_BLOCK_SIZE); 404 | increment_iv(temp_iv, AES_BLOCK_SIZE - 1 - mac_len); // Last argument is the byte size of the counting portion of the counter block. /*BUG?*/ 405 | aes_encrypt_ctr(out, payload_len, out, key, keysize, temp_iv); 406 | 407 | // Encrypt the MAC with CTR mode with a counter starting at 0. 408 | aes_encrypt_ctr(&out[payload_len], mac_len, &out[payload_len], key, keysize, counter); 409 | 410 | free(buf); 411 | *out_len = payload_len + mac_len; 412 | 413 | return(TRUE); 414 | } 415 | 416 | // plaintext_len = ciphertext_len - mac_len 417 | // Needs a flag for whether the MAC matches. 418 | int aes_decrypt_ccm(const BYTE ciphertext[], WORD ciphertext_len, const BYTE assoc[], unsigned short assoc_len, 419 | const BYTE nonce[], unsigned short nonce_len, BYTE plaintext[], WORD *plaintext_len, 420 | WORD mac_len, int *mac_auth, const BYTE key_str[], int keysize) 421 | { 422 | BYTE temp_iv[AES_BLOCK_SIZE], counter[AES_BLOCK_SIZE], mac[16], mac_buf[16], *buf; 423 | int end_of_buf, plaintext_len_store_size; 424 | WORD key[60]; 425 | 426 | if (ciphertext_len <= mac_len) 427 | return(FALSE); 428 | 429 | buf = (BYTE*)malloc(assoc_len + ciphertext_len /*ciphertext_len = plaintext_len + mac_len*/ + 48); 430 | if (! buf) 431 | return(FALSE); 432 | 433 | // Prepare the key for usage. 434 | aes_key_setup(key_str, key, keysize); 435 | 436 | // Copy the plaintext and MAC to the output buffers. 437 | *plaintext_len = ciphertext_len - mac_len; 438 | plaintext_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; 439 | memcpy(plaintext, ciphertext, *plaintext_len); 440 | memcpy(mac, &ciphertext[*plaintext_len], mac_len); 441 | 442 | // Prepare the first counter block for use in decryption. 443 | ccm_prepare_first_ctr_blk(counter, nonce, nonce_len, plaintext_len_store_size); 444 | 445 | // Decrypt the Payload with CTR mode with a counter starting at 1. 446 | memcpy(temp_iv, counter, AES_BLOCK_SIZE); 447 | increment_iv(temp_iv, AES_BLOCK_SIZE - 1 - mac_len); // (AES_BLOCK_SIZE - 1 - mac_len) is the byte size of the counting portion of the counter block. 448 | aes_decrypt_ctr(plaintext, *plaintext_len, plaintext, key, keysize, temp_iv); 449 | 450 | // Setting mac_auth to NULL disables the authentication check. 451 | if (mac_auth != NULL) { 452 | // Decrypt the MAC with CTR mode with a counter starting at 0. 453 | aes_decrypt_ctr(mac, mac_len, mac, key, keysize, counter); 454 | 455 | // Format the first block of the formatted data. 456 | plaintext_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; 457 | ccm_prepare_first_format_blk(buf, assoc_len, *plaintext_len, plaintext_len_store_size, mac_len, nonce, nonce_len); 458 | end_of_buf = AES_BLOCK_SIZE; 459 | 460 | // Format the Associated Data into the authentication buffer. 461 | ccm_format_assoc_data(buf, &end_of_buf, assoc, assoc_len); 462 | 463 | // Format the Payload into the authentication buffer. 464 | ccm_format_payload_data(buf, &end_of_buf, plaintext, *plaintext_len); 465 | 466 | // Perform the CBC operation with an IV of zeros on the formatted buffer to calculate the MAC. 467 | memset(temp_iv, 0, AES_BLOCK_SIZE); 468 | aes_encrypt_cbc_mac(buf, end_of_buf, mac_buf, key, keysize, temp_iv); 469 | 470 | // Compare the calculated MAC against the MAC embedded in the ciphertext to see if they are the same. 471 | if (! memcmp(mac, mac_buf, mac_len)) { 472 | *mac_auth = TRUE; 473 | } 474 | else { 475 | *mac_auth = FALSE; 476 | memset(plaintext, 0, *plaintext_len); 477 | } 478 | } 479 | 480 | free(buf); 481 | 482 | return(TRUE); 483 | } 484 | 485 | // Creates the first counter block. First byte is flags, then the nonce, then the incremented part. 486 | void ccm_prepare_first_ctr_blk(BYTE counter[], const BYTE nonce[], int nonce_len, int payload_len_store_size) 487 | { 488 | memset(counter, 0, AES_BLOCK_SIZE); 489 | counter[0] = (payload_len_store_size - 1) & 0x07; 490 | memcpy(&counter[1], nonce, nonce_len); 491 | } 492 | 493 | void ccm_prepare_first_format_blk(BYTE buf[], int assoc_len, int payload_len, int payload_len_store_size, int mac_len, const BYTE nonce[], int nonce_len) 494 | { 495 | // Set the flags for the first byte of the first block. 496 | buf[0] = ((((mac_len - 2) / 2) & 0x07) << 3) | ((payload_len_store_size - 1) & 0x07); 497 | if (assoc_len > 0) 498 | buf[0] += 0x40; 499 | // Format the rest of the first block, storing the nonce and the size of the payload. 500 | memcpy(&buf[1], nonce, nonce_len); 501 | memset(&buf[1 + nonce_len], 0, AES_BLOCK_SIZE - 1 - nonce_len); 502 | buf[15] = payload_len & 0x000000FF; 503 | buf[14] = (payload_len >> 8) & 0x000000FF; 504 | } 505 | 506 | void ccm_format_assoc_data(BYTE buf[], int *end_of_buf, const BYTE assoc[], int assoc_len) 507 | { 508 | int pad; 509 | 510 | buf[*end_of_buf + 1] = assoc_len & 0x00FF; 511 | buf[*end_of_buf] = (assoc_len >> 8) & 0x00FF; 512 | *end_of_buf += 2; 513 | memcpy(&buf[*end_of_buf], assoc, assoc_len); 514 | *end_of_buf += assoc_len; 515 | pad = AES_BLOCK_SIZE - (*end_of_buf % AES_BLOCK_SIZE); /*BUG?*/ 516 | memset(&buf[*end_of_buf], 0, pad); 517 | *end_of_buf += pad; 518 | } 519 | 520 | void ccm_format_payload_data(BYTE buf[], int *end_of_buf, const BYTE payload[], int payload_len) 521 | { 522 | int pad; 523 | 524 | memcpy(&buf[*end_of_buf], payload, payload_len); 525 | *end_of_buf += payload_len; 526 | pad = *end_of_buf % AES_BLOCK_SIZE; 527 | if (pad != 0) 528 | pad = AES_BLOCK_SIZE - pad; 529 | memset(&buf[*end_of_buf], 0, pad); 530 | *end_of_buf += pad; 531 | } 532 | 533 | /******************* 534 | * AES 535 | *******************/ 536 | ///////////////// 537 | // KEY EXPANSION 538 | ///////////////// 539 | 540 | // Substitutes a word using the AES S-Box. 541 | WORD SubWord(WORD word) 542 | { 543 | unsigned int result; 544 | 545 | result = (int)aes_sbox[(word >> 4) & 0x0000000F][word & 0x0000000F]; 546 | result += (int)aes_sbox[(word >> 12) & 0x0000000F][(word >> 8) & 0x0000000F] << 8; 547 | result += (int)aes_sbox[(word >> 20) & 0x0000000F][(word >> 16) & 0x0000000F] << 16; 548 | result += (int)aes_sbox[(word >> 28) & 0x0000000F][(word >> 24) & 0x0000000F] << 24; 549 | return(result); 550 | } 551 | 552 | // Performs the action of generating the keys that will be used in every round of 553 | // encryption. "key" is the user-supplied input key, "w" is the output key schedule, 554 | // "keysize" is the length in bits of "key", must be 128, 192, or 256. 555 | void aes_key_setup(const BYTE key[], WORD w[], int keysize) 556 | { 557 | int Nb=4,Nr,Nk,idx; 558 | WORD temp,Rcon[]={0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000, 559 | 0x40000000,0x80000000,0x1b000000,0x36000000,0x6c000000,0xd8000000, 560 | 0xab000000,0x4d000000,0x9a000000}; 561 | 562 | switch (keysize) { 563 | case 128: Nr = 10; Nk = 4; break; 564 | case 192: Nr = 12; Nk = 6; break; 565 | case 256: Nr = 14; Nk = 8; break; 566 | default: return; 567 | } 568 | 569 | for (idx=0; idx < Nk; ++idx) { 570 | w[idx] = ((key[4 * idx]) << 24) | ((key[4 * idx + 1]) << 16) | 571 | ((key[4 * idx + 2]) << 8) | ((key[4 * idx + 3])); 572 | } 573 | 574 | for (idx = Nk; idx < Nb * (Nr+1); ++idx) { 575 | temp = w[idx - 1]; 576 | if ((idx % Nk) == 0) 577 | temp = SubWord(KE_ROTWORD(temp)) ^ Rcon[(idx-1)/Nk]; 578 | else if (Nk > 6 && (idx % Nk) == 4) 579 | temp = SubWord(temp); 580 | w[idx] = w[idx-Nk] ^ temp; 581 | } 582 | } 583 | 584 | ///////////////// 585 | // ADD ROUND KEY 586 | ///////////////// 587 | 588 | // Performs the AddRoundKey step. Each round has its own pre-generated 16-byte key in the 589 | // form of 4 integers (the "w" array). Each integer is XOR'd by one column of the state. 590 | // Also performs the job of InvAddRoundKey(); since the function is a simple XOR process, 591 | // it is its own inverse. 592 | void AddRoundKey(BYTE state[][4], const WORD w[]) 593 | { 594 | BYTE subkey[4]; 595 | 596 | // memcpy(subkey,&w[idx],4); // Not accurate for big endian machines 597 | // Subkey 1 598 | subkey[0] = w[0] >> 24; 599 | subkey[1] = w[0] >> 16; 600 | subkey[2] = w[0] >> 8; 601 | subkey[3] = w[0]; 602 | state[0][0] ^= subkey[0]; 603 | state[1][0] ^= subkey[1]; 604 | state[2][0] ^= subkey[2]; 605 | state[3][0] ^= subkey[3]; 606 | // Subkey 2 607 | subkey[0] = w[1] >> 24; 608 | subkey[1] = w[1] >> 16; 609 | subkey[2] = w[1] >> 8; 610 | subkey[3] = w[1]; 611 | state[0][1] ^= subkey[0]; 612 | state[1][1] ^= subkey[1]; 613 | state[2][1] ^= subkey[2]; 614 | state[3][1] ^= subkey[3]; 615 | // Subkey 3 616 | subkey[0] = w[2] >> 24; 617 | subkey[1] = w[2] >> 16; 618 | subkey[2] = w[2] >> 8; 619 | subkey[3] = w[2]; 620 | state[0][2] ^= subkey[0]; 621 | state[1][2] ^= subkey[1]; 622 | state[2][2] ^= subkey[2]; 623 | state[3][2] ^= subkey[3]; 624 | // Subkey 4 625 | subkey[0] = w[3] >> 24; 626 | subkey[1] = w[3] >> 16; 627 | subkey[2] = w[3] >> 8; 628 | subkey[3] = w[3]; 629 | state[0][3] ^= subkey[0]; 630 | state[1][3] ^= subkey[1]; 631 | state[2][3] ^= subkey[2]; 632 | state[3][3] ^= subkey[3]; 633 | } 634 | 635 | ///////////////// 636 | // (Inv)SubBytes 637 | ///////////////// 638 | 639 | // Performs the SubBytes step. All bytes in the state are substituted with a 640 | // pre-calculated value from a lookup table. 641 | void SubBytes(BYTE state[][4]) 642 | { 643 | state[0][0] = aes_sbox[state[0][0] >> 4][state[0][0] & 0x0F]; 644 | state[0][1] = aes_sbox[state[0][1] >> 4][state[0][1] & 0x0F]; 645 | state[0][2] = aes_sbox[state[0][2] >> 4][state[0][2] & 0x0F]; 646 | state[0][3] = aes_sbox[state[0][3] >> 4][state[0][3] & 0x0F]; 647 | state[1][0] = aes_sbox[state[1][0] >> 4][state[1][0] & 0x0F]; 648 | state[1][1] = aes_sbox[state[1][1] >> 4][state[1][1] & 0x0F]; 649 | state[1][2] = aes_sbox[state[1][2] >> 4][state[1][2] & 0x0F]; 650 | state[1][3] = aes_sbox[state[1][3] >> 4][state[1][3] & 0x0F]; 651 | state[2][0] = aes_sbox[state[2][0] >> 4][state[2][0] & 0x0F]; 652 | state[2][1] = aes_sbox[state[2][1] >> 4][state[2][1] & 0x0F]; 653 | state[2][2] = aes_sbox[state[2][2] >> 4][state[2][2] & 0x0F]; 654 | state[2][3] = aes_sbox[state[2][3] >> 4][state[2][3] & 0x0F]; 655 | state[3][0] = aes_sbox[state[3][0] >> 4][state[3][0] & 0x0F]; 656 | state[3][1] = aes_sbox[state[3][1] >> 4][state[3][1] & 0x0F]; 657 | state[3][2] = aes_sbox[state[3][2] >> 4][state[3][2] & 0x0F]; 658 | state[3][3] = aes_sbox[state[3][3] >> 4][state[3][3] & 0x0F]; 659 | } 660 | 661 | void InvSubBytes(BYTE state[][4]) 662 | { 663 | state[0][0] = aes_invsbox[state[0][0] >> 4][state[0][0] & 0x0F]; 664 | state[0][1] = aes_invsbox[state[0][1] >> 4][state[0][1] & 0x0F]; 665 | state[0][2] = aes_invsbox[state[0][2] >> 4][state[0][2] & 0x0F]; 666 | state[0][3] = aes_invsbox[state[0][3] >> 4][state[0][3] & 0x0F]; 667 | state[1][0] = aes_invsbox[state[1][0] >> 4][state[1][0] & 0x0F]; 668 | state[1][1] = aes_invsbox[state[1][1] >> 4][state[1][1] & 0x0F]; 669 | state[1][2] = aes_invsbox[state[1][2] >> 4][state[1][2] & 0x0F]; 670 | state[1][3] = aes_invsbox[state[1][3] >> 4][state[1][3] & 0x0F]; 671 | state[2][0] = aes_invsbox[state[2][0] >> 4][state[2][0] & 0x0F]; 672 | state[2][1] = aes_invsbox[state[2][1] >> 4][state[2][1] & 0x0F]; 673 | state[2][2] = aes_invsbox[state[2][2] >> 4][state[2][2] & 0x0F]; 674 | state[2][3] = aes_invsbox[state[2][3] >> 4][state[2][3] & 0x0F]; 675 | state[3][0] = aes_invsbox[state[3][0] >> 4][state[3][0] & 0x0F]; 676 | state[3][1] = aes_invsbox[state[3][1] >> 4][state[3][1] & 0x0F]; 677 | state[3][2] = aes_invsbox[state[3][2] >> 4][state[3][2] & 0x0F]; 678 | state[3][3] = aes_invsbox[state[3][3] >> 4][state[3][3] & 0x0F]; 679 | } 680 | 681 | ///////////////// 682 | // (Inv)ShiftRows 683 | ///////////////// 684 | 685 | // Performs the ShiftRows step. All rows are shifted cylindrically to the left. 686 | void ShiftRows(BYTE state[][4]) 687 | { 688 | int t; 689 | 690 | // Shift left by 1 691 | t = state[1][0]; 692 | state[1][0] = state[1][1]; 693 | state[1][1] = state[1][2]; 694 | state[1][2] = state[1][3]; 695 | state[1][3] = t; 696 | // Shift left by 2 697 | t = state[2][0]; 698 | state[2][0] = state[2][2]; 699 | state[2][2] = t; 700 | t = state[2][1]; 701 | state[2][1] = state[2][3]; 702 | state[2][3] = t; 703 | // Shift left by 3 704 | t = state[3][0]; 705 | state[3][0] = state[3][3]; 706 | state[3][3] = state[3][2]; 707 | state[3][2] = state[3][1]; 708 | state[3][1] = t; 709 | } 710 | 711 | // All rows are shifted cylindrically to the right. 712 | void InvShiftRows(BYTE state[][4]) 713 | { 714 | int t; 715 | 716 | // Shift right by 1 717 | t = state[1][3]; 718 | state[1][3] = state[1][2]; 719 | state[1][2] = state[1][1]; 720 | state[1][1] = state[1][0]; 721 | state[1][0] = t; 722 | // Shift right by 2 723 | t = state[2][3]; 724 | state[2][3] = state[2][1]; 725 | state[2][1] = t; 726 | t = state[2][2]; 727 | state[2][2] = state[2][0]; 728 | state[2][0] = t; 729 | // Shift right by 3 730 | t = state[3][3]; 731 | state[3][3] = state[3][0]; 732 | state[3][0] = state[3][1]; 733 | state[3][1] = state[3][2]; 734 | state[3][2] = t; 735 | } 736 | 737 | ///////////////// 738 | // (Inv)MixColumns 739 | ///////////////// 740 | 741 | // Performs the MixColums step. The state is multiplied by itself using matrix 742 | // multiplication in a Galios Field 2^8. All multiplication is pre-computed in a table. 743 | // Addition is equivilent to XOR. (Must always make a copy of the column as the original 744 | // values will be destoyed.) 745 | void MixColumns(BYTE state[][4]) 746 | { 747 | BYTE col[4]; 748 | 749 | // Column 1 750 | col[0] = state[0][0]; 751 | col[1] = state[1][0]; 752 | col[2] = state[2][0]; 753 | col[3] = state[3][0]; 754 | state[0][0] = gf_mul[col[0]][0]; 755 | state[0][0] ^= gf_mul[col[1]][1]; 756 | state[0][0] ^= col[2]; 757 | state[0][0] ^= col[3]; 758 | state[1][0] = col[0]; 759 | state[1][0] ^= gf_mul[col[1]][0]; 760 | state[1][0] ^= gf_mul[col[2]][1]; 761 | state[1][0] ^= col[3]; 762 | state[2][0] = col[0]; 763 | state[2][0] ^= col[1]; 764 | state[2][0] ^= gf_mul[col[2]][0]; 765 | state[2][0] ^= gf_mul[col[3]][1]; 766 | state[3][0] = gf_mul[col[0]][1]; 767 | state[3][0] ^= col[1]; 768 | state[3][0] ^= col[2]; 769 | state[3][0] ^= gf_mul[col[3]][0]; 770 | // Column 2 771 | col[0] = state[0][1]; 772 | col[1] = state[1][1]; 773 | col[2] = state[2][1]; 774 | col[3] = state[3][1]; 775 | state[0][1] = gf_mul[col[0]][0]; 776 | state[0][1] ^= gf_mul[col[1]][1]; 777 | state[0][1] ^= col[2]; 778 | state[0][1] ^= col[3]; 779 | state[1][1] = col[0]; 780 | state[1][1] ^= gf_mul[col[1]][0]; 781 | state[1][1] ^= gf_mul[col[2]][1]; 782 | state[1][1] ^= col[3]; 783 | state[2][1] = col[0]; 784 | state[2][1] ^= col[1]; 785 | state[2][1] ^= gf_mul[col[2]][0]; 786 | state[2][1] ^= gf_mul[col[3]][1]; 787 | state[3][1] = gf_mul[col[0]][1]; 788 | state[3][1] ^= col[1]; 789 | state[3][1] ^= col[2]; 790 | state[3][1] ^= gf_mul[col[3]][0]; 791 | // Column 3 792 | col[0] = state[0][2]; 793 | col[1] = state[1][2]; 794 | col[2] = state[2][2]; 795 | col[3] = state[3][2]; 796 | state[0][2] = gf_mul[col[0]][0]; 797 | state[0][2] ^= gf_mul[col[1]][1]; 798 | state[0][2] ^= col[2]; 799 | state[0][2] ^= col[3]; 800 | state[1][2] = col[0]; 801 | state[1][2] ^= gf_mul[col[1]][0]; 802 | state[1][2] ^= gf_mul[col[2]][1]; 803 | state[1][2] ^= col[3]; 804 | state[2][2] = col[0]; 805 | state[2][2] ^= col[1]; 806 | state[2][2] ^= gf_mul[col[2]][0]; 807 | state[2][2] ^= gf_mul[col[3]][1]; 808 | state[3][2] = gf_mul[col[0]][1]; 809 | state[3][2] ^= col[1]; 810 | state[3][2] ^= col[2]; 811 | state[3][2] ^= gf_mul[col[3]][0]; 812 | // Column 4 813 | col[0] = state[0][3]; 814 | col[1] = state[1][3]; 815 | col[2] = state[2][3]; 816 | col[3] = state[3][3]; 817 | state[0][3] = gf_mul[col[0]][0]; 818 | state[0][3] ^= gf_mul[col[1]][1]; 819 | state[0][3] ^= col[2]; 820 | state[0][3] ^= col[3]; 821 | state[1][3] = col[0]; 822 | state[1][3] ^= gf_mul[col[1]][0]; 823 | state[1][3] ^= gf_mul[col[2]][1]; 824 | state[1][3] ^= col[3]; 825 | state[2][3] = col[0]; 826 | state[2][3] ^= col[1]; 827 | state[2][3] ^= gf_mul[col[2]][0]; 828 | state[2][3] ^= gf_mul[col[3]][1]; 829 | state[3][3] = gf_mul[col[0]][1]; 830 | state[3][3] ^= col[1]; 831 | state[3][3] ^= col[2]; 832 | state[3][3] ^= gf_mul[col[3]][0]; 833 | } 834 | 835 | void InvMixColumns(BYTE state[][4]) 836 | { 837 | BYTE col[4]; 838 | 839 | // Column 1 840 | col[0] = state[0][0]; 841 | col[1] = state[1][0]; 842 | col[2] = state[2][0]; 843 | col[3] = state[3][0]; 844 | state[0][0] = gf_mul[col[0]][5]; 845 | state[0][0] ^= gf_mul[col[1]][3]; 846 | state[0][0] ^= gf_mul[col[2]][4]; 847 | state[0][0] ^= gf_mul[col[3]][2]; 848 | state[1][0] = gf_mul[col[0]][2]; 849 | state[1][0] ^= gf_mul[col[1]][5]; 850 | state[1][0] ^= gf_mul[col[2]][3]; 851 | state[1][0] ^= gf_mul[col[3]][4]; 852 | state[2][0] = gf_mul[col[0]][4]; 853 | state[2][0] ^= gf_mul[col[1]][2]; 854 | state[2][0] ^= gf_mul[col[2]][5]; 855 | state[2][0] ^= gf_mul[col[3]][3]; 856 | state[3][0] = gf_mul[col[0]][3]; 857 | state[3][0] ^= gf_mul[col[1]][4]; 858 | state[3][0] ^= gf_mul[col[2]][2]; 859 | state[3][0] ^= gf_mul[col[3]][5]; 860 | // Column 2 861 | col[0] = state[0][1]; 862 | col[1] = state[1][1]; 863 | col[2] = state[2][1]; 864 | col[3] = state[3][1]; 865 | state[0][1] = gf_mul[col[0]][5]; 866 | state[0][1] ^= gf_mul[col[1]][3]; 867 | state[0][1] ^= gf_mul[col[2]][4]; 868 | state[0][1] ^= gf_mul[col[3]][2]; 869 | state[1][1] = gf_mul[col[0]][2]; 870 | state[1][1] ^= gf_mul[col[1]][5]; 871 | state[1][1] ^= gf_mul[col[2]][3]; 872 | state[1][1] ^= gf_mul[col[3]][4]; 873 | state[2][1] = gf_mul[col[0]][4]; 874 | state[2][1] ^= gf_mul[col[1]][2]; 875 | state[2][1] ^= gf_mul[col[2]][5]; 876 | state[2][1] ^= gf_mul[col[3]][3]; 877 | state[3][1] = gf_mul[col[0]][3]; 878 | state[3][1] ^= gf_mul[col[1]][4]; 879 | state[3][1] ^= gf_mul[col[2]][2]; 880 | state[3][1] ^= gf_mul[col[3]][5]; 881 | // Column 3 882 | col[0] = state[0][2]; 883 | col[1] = state[1][2]; 884 | col[2] = state[2][2]; 885 | col[3] = state[3][2]; 886 | state[0][2] = gf_mul[col[0]][5]; 887 | state[0][2] ^= gf_mul[col[1]][3]; 888 | state[0][2] ^= gf_mul[col[2]][4]; 889 | state[0][2] ^= gf_mul[col[3]][2]; 890 | state[1][2] = gf_mul[col[0]][2]; 891 | state[1][2] ^= gf_mul[col[1]][5]; 892 | state[1][2] ^= gf_mul[col[2]][3]; 893 | state[1][2] ^= gf_mul[col[3]][4]; 894 | state[2][2] = gf_mul[col[0]][4]; 895 | state[2][2] ^= gf_mul[col[1]][2]; 896 | state[2][2] ^= gf_mul[col[2]][5]; 897 | state[2][2] ^= gf_mul[col[3]][3]; 898 | state[3][2] = gf_mul[col[0]][3]; 899 | state[3][2] ^= gf_mul[col[1]][4]; 900 | state[3][2] ^= gf_mul[col[2]][2]; 901 | state[3][2] ^= gf_mul[col[3]][5]; 902 | // Column 4 903 | col[0] = state[0][3]; 904 | col[1] = state[1][3]; 905 | col[2] = state[2][3]; 906 | col[3] = state[3][3]; 907 | state[0][3] = gf_mul[col[0]][5]; 908 | state[0][3] ^= gf_mul[col[1]][3]; 909 | state[0][3] ^= gf_mul[col[2]][4]; 910 | state[0][3] ^= gf_mul[col[3]][2]; 911 | state[1][3] = gf_mul[col[0]][2]; 912 | state[1][3] ^= gf_mul[col[1]][5]; 913 | state[1][3] ^= gf_mul[col[2]][3]; 914 | state[1][3] ^= gf_mul[col[3]][4]; 915 | state[2][3] = gf_mul[col[0]][4]; 916 | state[2][3] ^= gf_mul[col[1]][2]; 917 | state[2][3] ^= gf_mul[col[2]][5]; 918 | state[2][3] ^= gf_mul[col[3]][3]; 919 | state[3][3] = gf_mul[col[0]][3]; 920 | state[3][3] ^= gf_mul[col[1]][4]; 921 | state[3][3] ^= gf_mul[col[2]][2]; 922 | state[3][3] ^= gf_mul[col[3]][5]; 923 | } 924 | 925 | ///////////////// 926 | // (En/De)Crypt 927 | ///////////////// 928 | 929 | void aes_encrypt(const BYTE in[], BYTE out[], const WORD key[], int keysize) 930 | { 931 | BYTE state[4][4]; 932 | 933 | // Copy input array (should be 16 bytes long) to a matrix (sequential bytes are ordered 934 | // by row, not col) called "state" for processing. 935 | // *** Implementation note: The official AES documentation references the state by 936 | // column, then row. Accessing an element in C requires row then column. Thus, all state 937 | // references in AES must have the column and row indexes reversed for C implementation. 938 | state[0][0] = in[0]; 939 | state[1][0] = in[1]; 940 | state[2][0] = in[2]; 941 | state[3][0] = in[3]; 942 | state[0][1] = in[4]; 943 | state[1][1] = in[5]; 944 | state[2][1] = in[6]; 945 | state[3][1] = in[7]; 946 | state[0][2] = in[8]; 947 | state[1][2] = in[9]; 948 | state[2][2] = in[10]; 949 | state[3][2] = in[11]; 950 | state[0][3] = in[12]; 951 | state[1][3] = in[13]; 952 | state[2][3] = in[14]; 953 | state[3][3] = in[15]; 954 | 955 | // Perform the necessary number of rounds. The round key is added first. 956 | // The last round does not perform the MixColumns step. 957 | AddRoundKey(state,&key[0]); 958 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[4]); 959 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[8]); 960 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[12]); 961 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[16]); 962 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[20]); 963 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[24]); 964 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[28]); 965 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[32]); 966 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[36]); 967 | if (keysize != 128) { 968 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[40]); 969 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[44]); 970 | if (keysize != 192) { 971 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[48]); 972 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[52]); 973 | SubBytes(state); ShiftRows(state); AddRoundKey(state,&key[56]); 974 | } 975 | else { 976 | SubBytes(state); ShiftRows(state); AddRoundKey(state,&key[48]); 977 | } 978 | } 979 | else { 980 | SubBytes(state); ShiftRows(state); AddRoundKey(state,&key[40]); 981 | } 982 | 983 | // Copy the state to the output array. 984 | out[0] = state[0][0]; 985 | out[1] = state[1][0]; 986 | out[2] = state[2][0]; 987 | out[3] = state[3][0]; 988 | out[4] = state[0][1]; 989 | out[5] = state[1][1]; 990 | out[6] = state[2][1]; 991 | out[7] = state[3][1]; 992 | out[8] = state[0][2]; 993 | out[9] = state[1][2]; 994 | out[10] = state[2][2]; 995 | out[11] = state[3][2]; 996 | out[12] = state[0][3]; 997 | out[13] = state[1][3]; 998 | out[14] = state[2][3]; 999 | out[15] = state[3][3]; 1000 | } 1001 | 1002 | void aes_decrypt(const BYTE in[], BYTE out[], const WORD key[], int keysize) 1003 | { 1004 | BYTE state[4][4]; 1005 | 1006 | // Copy the input to the state. 1007 | state[0][0] = in[0]; 1008 | state[1][0] = in[1]; 1009 | state[2][0] = in[2]; 1010 | state[3][0] = in[3]; 1011 | state[0][1] = in[4]; 1012 | state[1][1] = in[5]; 1013 | state[2][1] = in[6]; 1014 | state[3][1] = in[7]; 1015 | state[0][2] = in[8]; 1016 | state[1][2] = in[9]; 1017 | state[2][2] = in[10]; 1018 | state[3][2] = in[11]; 1019 | state[0][3] = in[12]; 1020 | state[1][3] = in[13]; 1021 | state[2][3] = in[14]; 1022 | state[3][3] = in[15]; 1023 | 1024 | // Perform the necessary number of rounds. The round key is added first. 1025 | // The last round does not perform the MixColumns step. 1026 | if (keysize > 128) { 1027 | if (keysize > 192) { 1028 | AddRoundKey(state,&key[56]); 1029 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[52]);InvMixColumns(state); 1030 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[48]);InvMixColumns(state); 1031 | } 1032 | else { 1033 | AddRoundKey(state,&key[48]); 1034 | } 1035 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[44]);InvMixColumns(state); 1036 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[40]);InvMixColumns(state); 1037 | } 1038 | else { 1039 | AddRoundKey(state,&key[40]); 1040 | } 1041 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[36]);InvMixColumns(state); 1042 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[32]);InvMixColumns(state); 1043 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[28]);InvMixColumns(state); 1044 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[24]);InvMixColumns(state); 1045 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[20]);InvMixColumns(state); 1046 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[16]);InvMixColumns(state); 1047 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[12]);InvMixColumns(state); 1048 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[8]);InvMixColumns(state); 1049 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[4]);InvMixColumns(state); 1050 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[0]); 1051 | 1052 | // Copy the state to the output array. 1053 | out[0] = state[0][0]; 1054 | out[1] = state[1][0]; 1055 | out[2] = state[2][0]; 1056 | out[3] = state[3][0]; 1057 | out[4] = state[0][1]; 1058 | out[5] = state[1][1]; 1059 | out[6] = state[2][1]; 1060 | out[7] = state[3][1]; 1061 | out[8] = state[0][2]; 1062 | out[9] = state[1][2]; 1063 | out[10] = state[2][2]; 1064 | out[11] = state[3][2]; 1065 | out[12] = state[0][3]; 1066 | out[13] = state[1][3]; 1067 | out[14] = state[2][3]; 1068 | out[15] = state[3][3]; 1069 | } 1070 | 1071 | /******************* 1072 | ** AES DEBUGGING FUNCTIONS 1073 | *******************/ 1074 | /* 1075 | // This prints the "state" grid as a linear hex string. 1076 | void print_state(BYTE state[][4]) 1077 | { 1078 | int idx,idx2; 1079 | 1080 | for (idx=0; idx < 4; idx++) 1081 | for (idx2=0; idx2 < 4; idx2++) 1082 | printf("%02x",state[idx2][idx]); 1083 | printf("\n"); 1084 | } 1085 | 1086 | // This prints the key (4 consecutive ints) used for a given round as a linear hex string. 1087 | void print_rnd_key(WORD key[]) 1088 | { 1089 | int idx; 1090 | 1091 | for (idx=0; idx < 4; idx++) 1092 | printf("%08x",key[idx]); 1093 | printf("\n"); 1094 | } 1095 | */ 1096 | 1097 | /*********************** FUNCTION DEFINITIONS ***********************/ 1098 | void print_hex(BYTE str[], int len) 1099 | { 1100 | int idx; 1101 | 1102 | for(idx = 0; idx < len; idx++) 1103 | printf("%02x", str[idx]); 1104 | } 1105 | 1106 | int aes_ecb_test() 1107 | { 1108 | WORD key_schedule[60], idx; 1109 | BYTE enc_buf[128]; 1110 | BYTE plaintext[2][16] = { 1111 | {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a}, 1112 | {0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} 1113 | }; 1114 | BYTE ciphertext[2][16] = { 1115 | {0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c,0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8}, 1116 | {0x59,0x1c,0xcb,0x10,0xd4,0x10,0xed,0x26,0xdc,0x5b,0xa7,0x4a,0x31,0x36,0x28,0x70} 1117 | }; 1118 | BYTE key[1][32] = { 1119 | {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} 1120 | }; 1121 | int pass = 1; 1122 | 1123 | // Raw ECB mode. 1124 | printf("* ECB mode:\n"); 1125 | aes_key_setup(key[0], key_schedule, 256); 1126 | printf( "Key : "); 1127 | print_hex(key[0], 32); 1128 | 1129 | for(idx = 0; idx < 2; idx++) { 1130 | aes_encrypt(plaintext[idx], enc_buf, key_schedule, 256); 1131 | printf("\nPlaintext : "); 1132 | print_hex(plaintext[idx], 16); 1133 | printf("\n-encrypted to: "); 1134 | print_hex(enc_buf, 16); 1135 | pass = pass && !memcmp(enc_buf, ciphertext[idx], 16); 1136 | 1137 | aes_decrypt(ciphertext[idx], enc_buf, key_schedule, 256); 1138 | printf("\nCiphertext : "); 1139 | print_hex(ciphertext[idx], 16); 1140 | printf("\n-decrypted to: "); 1141 | print_hex(enc_buf, 16); 1142 | pass = pass && !memcmp(enc_buf, plaintext[idx], 16); 1143 | 1144 | printf("\n\n"); 1145 | } 1146 | 1147 | return(pass); 1148 | } 1149 | 1150 | int aes_cbc_test() 1151 | { 1152 | WORD key_schedule[60]; 1153 | BYTE enc_buf[128]; 1154 | BYTE plaintext[1][32] = { 1155 | {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} 1156 | }; 1157 | BYTE ciphertext[1][32] = { 1158 | {0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba,0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6,0x9c,0xfc,0x4e,0x96,0x7e,0xdb,0x80,0x8d,0x67,0x9f,0x77,0x7b,0xc6,0x70,0x2c,0x7d} 1159 | }; 1160 | BYTE iv[1][16] = { 1161 | {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f} 1162 | }; 1163 | BYTE key[1][32] = { 1164 | {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} 1165 | }; 1166 | int pass = 1; 1167 | 1168 | printf("* CBC mode:\n"); 1169 | aes_key_setup(key[0], key_schedule, 256); 1170 | 1171 | printf( "Key : "); 1172 | print_hex(key[0], 32); 1173 | printf("\nIV : "); 1174 | print_hex(iv[0], 16); 1175 | 1176 | aes_encrypt_cbc(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]); 1177 | printf("\nPlaintext : "); 1178 | print_hex(plaintext[0], 32); 1179 | printf("\n-encrypted to: "); 1180 | print_hex(enc_buf, 32); 1181 | printf("\nCiphertext : "); 1182 | print_hex(ciphertext[0], 32); 1183 | pass = pass && !memcmp(enc_buf, ciphertext[0], 32); 1184 | 1185 | aes_decrypt_cbc(ciphertext[0], 32, enc_buf, key_schedule, 256, iv[0]); 1186 | printf("\nCiphertext : "); 1187 | print_hex(ciphertext[0], 32); 1188 | printf("\n-decrypted to: "); 1189 | print_hex(enc_buf, 32); 1190 | printf("\nPlaintext : "); 1191 | print_hex(plaintext[0], 32); 1192 | pass = pass && !memcmp(enc_buf, plaintext[0], 32); 1193 | 1194 | printf("\n\n"); 1195 | return(pass); 1196 | } 1197 | 1198 | int aes_ctr_test() 1199 | { 1200 | WORD key_schedule[60]; 1201 | BYTE enc_buf[128]; 1202 | BYTE plaintext[1][32] = { 1203 | {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} 1204 | }; 1205 | BYTE ciphertext[1][32] = { 1206 | {0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5,0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28,0xf4,0x43,0xe3,0xca,0x4d,0x62,0xb5,0x9a,0xca,0x84,0xe9,0x90,0xca,0xca,0xf5,0xc5} 1207 | }; 1208 | BYTE iv[1][16] = { 1209 | {0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff}, 1210 | }; 1211 | BYTE key[1][32] = { 1212 | {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} 1213 | }; 1214 | int pass = 1; 1215 | 1216 | printf("* CTR mode:\n"); 1217 | aes_key_setup(key[0], key_schedule, 256); 1218 | 1219 | printf( "Key : "); 1220 | print_hex(key[0], 32); 1221 | printf("\nIV : "); 1222 | print_hex(iv[0], 16); 1223 | 1224 | aes_encrypt_ctr(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]); 1225 | printf("\nPlaintext : "); 1226 | print_hex(plaintext[0], 32); 1227 | printf("\n-encrypted to: "); 1228 | print_hex(enc_buf, 32); 1229 | pass = pass && !memcmp(enc_buf, ciphertext[0], 32); 1230 | 1231 | aes_decrypt_ctr(ciphertext[0], 32, enc_buf, key_schedule, 256, iv[0]); 1232 | printf("\nCiphertext : "); 1233 | print_hex(ciphertext[0], 32); 1234 | printf("\n-decrypted to: "); 1235 | print_hex(enc_buf, 32); 1236 | pass = pass && !memcmp(enc_buf, plaintext[0], 32); 1237 | 1238 | printf("\n\n"); 1239 | return(pass); 1240 | } 1241 | 1242 | int aes_ccm_test() 1243 | { 1244 | int mac_auth; 1245 | WORD enc_buf_len; 1246 | BYTE enc_buf[128]; 1247 | BYTE plaintext[3][32] = { 1248 | {0x20,0x21,0x22,0x23}, 1249 | {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f}, 1250 | {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37} 1251 | }; 1252 | BYTE assoc[3][32] = { 1253 | {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, 1254 | {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}, 1255 | {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13} 1256 | }; 1257 | BYTE ciphertext[3][32 + 16] = { 1258 | {0x71,0x62,0x01,0x5b,0x4d,0xac,0x25,0x5d}, 1259 | {0xd2,0xa1,0xf0,0xe0,0x51,0xea,0x5f,0x62,0x08,0x1a,0x77,0x92,0x07,0x3d,0x59,0x3d,0x1f,0xc6,0x4f,0xbf,0xac,0xcd}, 1260 | {0xe3,0xb2,0x01,0xa9,0xf5,0xb7,0x1a,0x7a,0x9b,0x1c,0xea,0xec,0xcd,0x97,0xe7,0x0b,0x61,0x76,0xaa,0xd9,0xa4,0x42,0x8a,0xa5,0x48,0x43,0x92,0xfb,0xc1,0xb0,0x99,0x51} 1261 | }; 1262 | BYTE iv[3][16] = { 1263 | {0x10,0x11,0x12,0x13,0x14,0x15,0x16}, 1264 | {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17}, 1265 | {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b} 1266 | }; 1267 | BYTE key[1][32] = { 1268 | {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f} 1269 | }; 1270 | int pass = 1; 1271 | 1272 | printf("* CCM mode:\n"); 1273 | printf("Key : "); 1274 | print_hex(key[0], 16); 1275 | 1276 | print_hex(plaintext[0], 4); 1277 | print_hex(assoc[0], 8); 1278 | print_hex(ciphertext[0], 8); 1279 | print_hex(iv[0], 7); 1280 | print_hex(key[0], 16); 1281 | 1282 | aes_encrypt_ccm(plaintext[0], 4, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, key[0], 128); 1283 | printf("\nNONCE : "); 1284 | print_hex(iv[0], 7); 1285 | printf("\nAssoc. Data : "); 1286 | print_hex(assoc[0], 8); 1287 | printf("\nPayload : "); 1288 | print_hex(plaintext[0], 4); 1289 | printf("\n-encrypted to: "); 1290 | print_hex(enc_buf, enc_buf_len); 1291 | pass = pass && !memcmp(enc_buf, ciphertext[0], enc_buf_len); 1292 | 1293 | aes_decrypt_ccm(ciphertext[0], 8, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, &mac_auth, key[0], 128); 1294 | printf("\n-Ciphertext : "); 1295 | print_hex(ciphertext[0], 8); 1296 | printf("\n-decrypted to: "); 1297 | print_hex(enc_buf, enc_buf_len); 1298 | printf("\nAuthenticated: %d ", mac_auth); 1299 | pass = pass && !memcmp(enc_buf, plaintext[0], enc_buf_len) && mac_auth; 1300 | 1301 | 1302 | aes_encrypt_ccm(plaintext[1], 16, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, key[0], 128); 1303 | printf("\n\nNONCE : "); 1304 | print_hex(iv[1], 8); 1305 | printf("\nAssoc. Data : "); 1306 | print_hex(assoc[1], 16); 1307 | printf("\nPayload : "); 1308 | print_hex(plaintext[1], 16); 1309 | printf("\n-encrypted to: "); 1310 | print_hex(enc_buf, enc_buf_len); 1311 | pass = pass && !memcmp(enc_buf, ciphertext[1], enc_buf_len); 1312 | 1313 | aes_decrypt_ccm(ciphertext[1], 22, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, &mac_auth, key[0], 128); 1314 | printf("\n-Ciphertext : "); 1315 | print_hex(ciphertext[1], 22); 1316 | printf("\n-decrypted to: "); 1317 | print_hex(enc_buf, enc_buf_len); 1318 | printf("\nAuthenticated: %d ", mac_auth); 1319 | pass = pass && !memcmp(enc_buf, plaintext[1], enc_buf_len) && mac_auth; 1320 | 1321 | 1322 | aes_encrypt_ccm(plaintext[2], 24, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, key[0], 128); 1323 | printf("\n\nNONCE : "); 1324 | print_hex(iv[2], 12); 1325 | printf("\nAssoc. Data : "); 1326 | print_hex(assoc[2], 20); 1327 | printf("\nPayload : "); 1328 | print_hex(plaintext[2], 24); 1329 | printf("\n-encrypted to: "); 1330 | print_hex(enc_buf, enc_buf_len); 1331 | pass = pass && !memcmp(enc_buf, ciphertext[2], enc_buf_len); 1332 | 1333 | aes_decrypt_ccm(ciphertext[2], 32, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, &mac_auth, key[0], 128); 1334 | printf("\n-Ciphertext : "); 1335 | print_hex(ciphertext[2], 32); 1336 | printf("\n-decrypted to: "); 1337 | print_hex(enc_buf, enc_buf_len); 1338 | printf("\nAuthenticated: %d ", mac_auth); 1339 | pass = pass && !memcmp(enc_buf, plaintext[2], enc_buf_len) && mac_auth; 1340 | 1341 | printf("\n\n"); 1342 | return(pass); 1343 | } 1344 | 1345 | int aes_test() 1346 | { 1347 | int pass = 1; 1348 | 1349 | pass = pass && aes_ecb_test(); 1350 | pass = pass && aes_cbc_test(); 1351 | pass = pass && aes_ctr_test(); 1352 | pass = pass && aes_ccm_test(); 1353 | 1354 | return(pass); 1355 | } 1356 | 1357 | int main(int argc, char *argv[]) 1358 | { 1359 | printf("AES Tests: %s\n", aes_test() ? "SUCCEEDED" : "FAILED"); 1360 | 1361 | return(0); 1362 | } 1363 | -------------------------------------------------------------------------------- /examples/aes.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: aes.h 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: Defines the API for the corresponding AES implementation. 7 | *********************************************************************/ 8 | 9 | #ifndef AES_H 10 | #define AES_H 11 | 12 | /*************************** HEADER FILES ***************************/ 13 | #include 14 | 15 | /****************************** MACROS ******************************/ 16 | #define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time 17 | 18 | /**************************** DATA TYPES ****************************/ 19 | typedef unsigned char BYTE; // 8-bit byte 20 | typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines 21 | 22 | /*********************** FUNCTION DECLARATIONS **********************/ 23 | /////////////////// 24 | // AES 25 | /////////////////// 26 | // Key setup must be done before any AES en/de-cryption functions can be used. 27 | void aes_key_setup(const BYTE key[], // The key, must be 128, 192, or 256 bits 28 | WORD w[], // Output key schedule to be used later 29 | int keysize); // Bit length of the key, 128, 192, or 256 30 | 31 | void aes_encrypt(const BYTE in[], // 16 bytes of plaintext 32 | BYTE out[], // 16 bytes of ciphertext 33 | const WORD key[], // From the key setup 34 | int keysize); // Bit length of the key, 128, 192, or 256 35 | 36 | void aes_decrypt(const BYTE in[], // 16 bytes of ciphertext 37 | BYTE out[], // 16 bytes of plaintext 38 | const WORD key[], // From the key setup 39 | int keysize); // Bit length of the key, 128, 192, or 256 40 | 41 | /////////////////// 42 | // AES - CBC 43 | /////////////////// 44 | int aes_encrypt_cbc(const BYTE in[], // Plaintext 45 | size_t in_len, // Must be a multiple of AES_BLOCK_SIZE 46 | BYTE out[], // Ciphertext, same length as plaintext 47 | const WORD key[], // From the key setup 48 | int keysize, // Bit length of the key, 128, 192, or 256 49 | const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long 50 | 51 | int aes_decrypt_cbc(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]); 52 | 53 | // Only output the CBC-MAC of the input. 54 | int aes_encrypt_cbc_mac(const BYTE in[], // plaintext 55 | size_t in_len, // Must be a multiple of AES_BLOCK_SIZE 56 | BYTE out[], // Output MAC 57 | const WORD key[], // From the key setup 58 | int keysize, // Bit length of the key, 128, 192, or 256 59 | const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long 60 | 61 | /////////////////// 62 | // AES - CTR 63 | /////////////////// 64 | void increment_iv(BYTE iv[], // Must be a multiple of AES_BLOCK_SIZE 65 | int counter_size); // Bytes of the IV used for counting (low end) 66 | 67 | void aes_encrypt_ctr(const BYTE in[], // Plaintext 68 | size_t in_len, // Any byte length 69 | BYTE out[], // Ciphertext, same length as plaintext 70 | const WORD key[], // From the key setup 71 | int keysize, // Bit length of the key, 128, 192, or 256 72 | const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long 73 | 74 | void aes_decrypt_ctr(const BYTE in[], // Ciphertext 75 | size_t in_len, // Any byte length 76 | BYTE out[], // Plaintext, same length as ciphertext 77 | const WORD key[], // From the key setup 78 | int keysize, // Bit length of the key, 128, 192, or 256 79 | const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long 80 | 81 | /////////////////// 82 | // AES - CCM 83 | /////////////////// 84 | // Returns True if the input parameters do not violate any constraint. 85 | int aes_encrypt_ccm(const BYTE plaintext[], // IN - Plaintext. 86 | WORD plaintext_len, // IN - Plaintext length. 87 | const BYTE associated_data[], // IN - Associated Data included in authentication, but not encryption. 88 | unsigned short associated_data_len, // IN - Associated Data length in bytes. 89 | const BYTE nonce[], // IN - The Nonce to be used for encryption. 90 | unsigned short nonce_len, // IN - Nonce length in bytes. 91 | BYTE ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC. 92 | WORD *ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len. 93 | WORD mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16. 94 | const BYTE key[], // IN - The AES key for encryption. 95 | int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256. 96 | 97 | // Returns True if the input parameters do not violate any constraint. 98 | // Use mac_auth to ensure decryption/validation was preformed correctly. 99 | // If authentication does not succeed, the plaintext is zeroed out. To overwride 100 | // this, call with mac_auth = NULL. The proper proceedure is to decrypt with 101 | // authentication enabled (mac_auth != NULL) and make a second call to that 102 | // ignores authentication explicitly if the first call failes. 103 | int aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC. 104 | WORD ciphertext_len, // IN - Ciphertext length in bytes. 105 | const BYTE assoc[], // IN - The Associated Data, required for authentication. 106 | unsigned short assoc_len, // IN - Associated Data length in bytes. 107 | const BYTE nonce[], // IN - The Nonce to use for decryption, same one as for encryption. 108 | unsigned short nonce_len, // IN - Nonce length in bytes. 109 | BYTE plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len - mac_len. 110 | WORD *plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len . 111 | WORD mac_len, // IN - The length of the MAC that was calculated. 112 | int *mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the authentication. 113 | const BYTE key[], // IN - The AES key for decryption. 114 | int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256. 115 | 116 | /////////////////// 117 | // Test functions 118 | /////////////////// 119 | int aes_test(); 120 | int aes_ecb_test(); 121 | int aes_cbc_test(); 122 | int aes_ctr_test(); 123 | int aes_ccm_test(); 124 | 125 | #endif // AES_H 126 | -------------------------------------------------------------------------------- /examples/aes.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/aes.tgz -------------------------------------------------------------------------------- /examples/aes_asm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/aes_asm.png -------------------------------------------------------------------------------- /examples/aes_cfg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/aes_cfg.png -------------------------------------------------------------------------------- /examples/homeomorphism.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/homeomorphism.gif -------------------------------------------------------------------------------- /examples/homeomorphism_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/homeomorphism_1.gif -------------------------------------------------------------------------------- /examples/homeomorphism_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/homeomorphism_2.gif -------------------------------------------------------------------------------- /examples/mines.c: -------------------------------------------------------------------------------- 1 | /* adapted from https://github.com/SaidinWoT/minesweeper */ 2 | /* 3 | * NCurses Minesweeper with arrow keys! 4 | */ 5 | 6 | typedef unsigned int _Bool; 7 | 8 | #include 9 | #include 10 | #include 11 | #define ROWS 8 12 | #define COLS 8 13 | #define MINES 10 14 | #define pair(y,x) game[y][x] % 2 == -1 ? 1 : (game[y][x] < 0 ? 2 : 3) 15 | 16 | /* 17 | * game array 18 | * Tracks values of each square 19 | * Squares each maintain a single integer value to indicate their state: 20 | * A value of... 21 | * 0 or greater indicates a checked spot with that number of 22 | * mines in the adjacent squares 23 | * 24 | * -2 indicates an unflagged, unchecked, empty spot 25 | * 26 | * -3 indicates a flagged, unchecked, empty spot 27 | * 28 | * -4 indicates an unflagged, unchecked spot containing a mine 29 | * 30 | * -5 indicates a flagged, unchecked spot containing a mine 31 | */ 32 | int game[ROWS][COLS]; 33 | int cursY, cursX; //Track the current cursor location 34 | int i, j; //Globally used for coordinate manipulation 35 | int mines, clean, flags; //Tracking of number of mines, clean spots, and remaining flags, respectively 36 | 37 | void printSpot(int row, int col); 38 | int takeTurn(); 39 | int checkSpot(int row, int col); 40 | int checkAround(int row, int col, int opt); 41 | void moveCursor(); 42 | void endGame(); 43 | 44 | int main() { 45 | initscr(); 46 | if(has_colors() == TRUE) { 47 | start_color(); 48 | init_pair(1, COLOR_BLACK, COLOR_YELLOW); 49 | init_pair(2, COLOR_WHITE, COLOR_BLUE); 50 | init_pair(3, COLOR_BLACK, COLOR_CYAN); 51 | init_pair(4, COLOR_RED, COLOR_CYAN); 52 | init_pair(5, COLOR_RED, COLOR_YELLOW); 53 | } 54 | cbreak(); 55 | keypad(stdscr, TRUE); 56 | curs_set(0); 57 | 58 | srand(time(0)); 59 | for(i = 0; i < ROWS; i++) { 60 | for(j = 0; j < COLS; j++) { 61 | game[i][j] = -2; 62 | printSpot(i, j); 63 | } 64 | } 65 | //mvchgat(cursY, 3*cursX, 3, A_REVERSE, pair(cursY, cursX), NULL); 66 | attron(A_REVERSE); 67 | printSpot(cursY, cursX); 68 | attroff(A_REVERSE); 69 | 70 | mines=MINES; 71 | /* 72 | do { 73 | mvprintw(ROWS+1, 0, "How many mines would you like? "); 74 | clrtobot(); 75 | scanw("%2d", &mines); 76 | } while(mines < 1); 77 | */ 78 | noecho(); 79 | flags = mines; 80 | clean = (ROWS * COLS) - mines; 81 | mvprintw(ROWS+1, 0, "Flags Remaining: %02d", flags); 82 | clrtobot(); 83 | mvprintw(ROWS+2, 0, "(move:wasd flag:f step:c quit:q)"); 84 | clrtobot(); 85 | 86 | while(takeTurn()) {} 87 | endGame(); 88 | endwin(); 89 | 90 | return 0; 91 | } 92 | 93 | void printSpot(int row, int col) { 94 | attron(COLOR_PAIR(pair(row, col))); 95 | if(game[row][col] > 0) { 96 | mvprintw(row, 3*col, "[%d]", game[row][col]); 97 | } else { 98 | mvprintw(row, 3*col, game[row][col] % 2 == -1 ? "[F]" : (game[row][col] < 0 ? "[?]" : " ")); 99 | } 100 | attroff(COLOR_PAIR(pair(row, col))); 101 | } 102 | 103 | int takeTurn() { 104 | moveCursor(); 105 | if(mines > 0) { 106 | game[cursY][cursX] -= 2; 107 | while(mines > 0) { 108 | i = rand()%ROWS; 109 | j = rand()%COLS; 110 | if(game[i][j] > -4) { 111 | game[i][j] = (game[i][j] % 2) - 4; 112 | mines--; 113 | } 114 | } 115 | game[cursY][cursX] += 2; 116 | } 117 | return checkSpot(cursY, cursX); 118 | } 119 | 120 | int checkSpot(int row, int col) { 121 | if(game[row][col] == -2) { 122 | game[row][col] = checkAround(row, col, 0); 123 | if(game[row][col] == 0) { 124 | checkAround(row, col, 1); 125 | } 126 | printSpot(row, col); 127 | return --clean; 128 | } else if(game[row][col] > 0 && game[row][col] == checkAround(row, col, 2)) { 129 | return checkAround(row, col, 3); 130 | } else if(game[row][col] == -4) { 131 | return 0; 132 | } 133 | return 1; 134 | } 135 | 136 | int checkAround(int row, int col, int opt) { 137 | int y, x, total = 0; 138 | for(y = row < 1 ? 0 : row - 1; y <= (row == ROWS - 1 ? ROWS - 1 : row + 1); y++) { 139 | for(x = col < 1 ? 0 : col - 1; x <= (col == COLS - 1 ? COLS - 1 : col + 1); x++) { 140 | if(opt == 0 && game[y][x] <= -4) { 141 | total++; 142 | } else if(opt == 1 && game[y][x] / 2 == -1) { 143 | checkSpot(y, x); 144 | } else if(opt == 2 && game[y][x] % 2 == -1) { 145 | total++; 146 | } else if(opt == 3 && game[y][x] < 0) { 147 | total++; 148 | if(checkSpot(y, x) == 0) { 149 | return 0; 150 | } 151 | } 152 | } 153 | } 154 | return total; 155 | } 156 | 157 | void moveCursor() { 158 | static int ch; 159 | for(ch = getch(); ch != 'c' && ch != ' ' && ch != '\n'; ch = getch()) { 160 | //mvchgat(cursY, 3*cursX, 3, A_NORMAL, pair(cursY, cursX), NULL); 161 | printSpot(cursY, cursX); 162 | switch(ch) { 163 | case 'w': 164 | case 'k': 165 | case KEY_UP: 166 | cursY = (cursY + ROWS - 1) % ROWS; 167 | break; 168 | case 'a': 169 | case 'h': 170 | case KEY_LEFT: 171 | cursX = (cursX + COLS - 1) % COLS; 172 | break; 173 | case 's': 174 | case 'j': 175 | case KEY_DOWN: 176 | cursY = (cursY + ROWS + 1) % ROWS; 177 | break; 178 | case 'd': 179 | case 'l': 180 | case KEY_RIGHT: 181 | cursX = (cursX + COLS + 1) % COLS; 182 | break; 183 | case 'f': 184 | if(game[cursY][cursX] % 2 == -1) { 185 | game[cursY][cursX]++; 186 | flags++; 187 | } else if(game[cursY][cursX] < 0 && flags > 0) { 188 | game[cursY][cursX]--; 189 | flags--; 190 | } 191 | mvprintw(ROWS+1, 17, "%02d", flags); 192 | printSpot(cursY, cursX); 193 | break; 194 | case 'q': 195 | endwin(); 196 | exit(0); 197 | } 198 | //mvchgat(cursY, 3*cursX, 3, A_REVERSE, pair(cursY, cursX), NULL); 199 | attron(A_REVERSE); 200 | printSpot(cursY, cursX); 201 | attroff(A_REVERSE); 202 | } 203 | } 204 | 205 | void endGame() { 206 | if(clean > 0) { 207 | for(i = 0; i < ROWS; i++) { 208 | for(j = 0; j < COLS; j++) { 209 | if((game[i][j] - 1) / 2 == -2) { 210 | attron(COLOR_PAIR(game[i][j] == -4 ? 4 : 5)); 211 | mvprintw(i, 3*j, " "); 212 | mvaddch(i, (3*j)+1, game[i][j] == -4 ? ACS_DIAMOND : 'X'); 213 | attroff(COLOR_PAIR(game[i][j] == -4 ? 4 : 5)); 214 | } 215 | } 216 | } 217 | } 218 | attron(COLOR_PAIR(1) | A_BOLD); 219 | mvprintw(ROWS+1, 0, clean > 0 ? "YOU LOST!" : "EPIC WINZ!"); 220 | attroff(COLOR_PAIR(1) | A_BOLD); 221 | clrtoeol(); 222 | getch(); 223 | } 224 | -------------------------------------------------------------------------------- /examples/mines.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/mines.tgz -------------------------------------------------------------------------------- /examples/mines_asm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/mines_asm.png -------------------------------------------------------------------------------- /examples/mines_cfg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xoreaxeaxeax/reductio/7b04319ecb1bb9e516ee394d4c15b2b47c534ce8/examples/mines_cfg.png -------------------------------------------------------------------------------- /reductio.py: -------------------------------------------------------------------------------- 1 | # 2 | # reductio ad absurdum 3 | # 4 | # a proof of concept 5 | # : all programs can be reduced to the same instruction stream. 6 | # 7 | 8 | # 9 | # github.com/xoreaxeaxeax/reductio // domas // @xoreaxeaxeax 10 | # 11 | 12 | import sys 13 | import hashlib 14 | import re 15 | import os 16 | import subprocess 17 | 18 | XFER_SIZE = 4 19 | 20 | def ismem(term): 21 | return "(" in term or "%" not in term 22 | 23 | def compose(offset, base, index, scale): 24 | if not base and not index and not scale: 25 | return "(%s)" % offset 26 | elif not index and not scale: 27 | return "%s(%s)" % (offset, base) 28 | elif not scale: 29 | return "%s(%s,%s,1)" % (offset, base, index) 30 | else: 31 | return "%s(%s,%s,%s)" % (offset, base, index, scale) 32 | 33 | def decompose(term): 34 | offset = base = index = scale = "" 35 | r = re.compile(r'(.*)\((%.*),(%.*),(.*)\)') 36 | if r.match(term): 37 | (offset,base,index,scale) = r.search(term).groups() 38 | else: 39 | r = re.compile(r'(.*)\(,(%.*),(.*)\)') 40 | if r.match(term): 41 | (offset,index,scale) = r.search(term).groups() 42 | else: 43 | r = re.compile(r'(.*)\((%.*),(%.*)\)') 44 | if r.match(term): 45 | (offset,base,index) = r.search(term).groups() 46 | else: 47 | r = re.compile(r'(.*)\((%.*)\)') 48 | if r.match(term): 49 | (offset,base) = r.search(term).groups() 50 | else: 51 | r = re.compile(r'\((.*)\)') 52 | if r.match(term): 53 | (offset,) = r.search(term).groups() 54 | else: 55 | r = re.compile(r'(.*)') 56 | if r.match(term): 57 | (offset,) = r.search(term).groups() 58 | else: 59 | raise Exception 60 | return (offset, base, index, scale) 61 | 62 | BAR_LENGTH = 50 63 | BAR_REFRESH = .001 # .001 64 | def progress(p, l): 65 | if l < 1: 66 | l = 1 67 | if p / float(l) > progress.last + BAR_REFRESH or p == l: 68 | progress.last = p / float(l) 69 | sys.stdout.write( 70 | " [%s%s] %6.1f%%" % 71 | ("-" * (p * BAR_LENGTH / l), 72 | " " * (BAR_LENGTH - p * BAR_LENGTH / l), 73 | (progress.last * 100)) 74 | ) 75 | sys.stdout.write("\b" * (BAR_LENGTH + 3 + 8)) 76 | sys.stdout.flush() 77 | if p == l: 78 | progress.last = 0 79 | progress.last = 0 80 | 81 | def load(s): 82 | with open(s) as f: 83 | asm = f.readlines() 84 | return asm 85 | 86 | # aes becomes a 2gb file. gnu assembler doesn't like that. 87 | # break it into pieces. 88 | # (hence the 'globals' throughout this - 89 | # everything needs to be visible to linker) 90 | MAX_ASM_LINES = 100000 91 | def break_write(s, asm): 92 | i = 0 93 | c = 0 94 | while c < len(asm): 95 | with open("%s%03d" % (s, i), 'w') as f: 96 | f.write(".data\n") # super-hack - as will assume .text 97 | for p, l in enumerate(asm[c:c+MAX_ASM_LINES]): 98 | progress(c, len(asm)-1) 99 | if p != 0 and ".balign" in l: 100 | # another hack. this one was frustrating and cost hours 101 | # to track down. the gas .align directive pads the 102 | # current location _and_ forces an alignment of the 103 | # entire section in the resulting object. although this 104 | # makes sense in hindsight, it isn't documented, and 105 | # caused a lot of mysterious breaking (when a table not 106 | # containing an .align gets split across multiple 107 | # objects, and a subsequent .align causes padding to be 108 | # injected into the middle of the table to try to align 109 | # the entire section). to "fix" - ensure the alignment 110 | # does not occur in the middle of an object. 111 | break 112 | f.write(l) 113 | c = c + 1 114 | # assume global directives are always above their label 115 | # (not a safe assumption) 116 | # and keep directive and label together 117 | if asm[c-1].startswith(".glob"): 118 | f.write(asm[c]) 119 | c = c + 1 120 | i = i + 1 121 | return ["%s%03d" % (s, k) for k in range(i)] 122 | 123 | def write(s, asm): 124 | with open(s, 'w') as f: 125 | for p, l in enumerate(asm): 126 | progress(p, len(asm)-1) 127 | f.write(l) 128 | 129 | # pass 0: 130 | # separate execution loop from environment setup 131 | def remove_prologue(asm): 132 | pasm = [] 133 | prologue = [] 134 | found_prologue = False 135 | for p, l in enumerate(asm): 136 | progress(p, len(asm)-1) 137 | if "master_loop" in l: 138 | found_prologue = True 139 | if found_prologue: 140 | pasm.append(l) 141 | else: 142 | prologue.append(l) 143 | if not found_prologue: 144 | for l in prologue: 145 | pasm.append(l) 146 | prologue = [] 147 | 148 | return [pasm,prologue] 149 | 150 | # pass 1: 151 | # replace all constant references with memory references instead 152 | def pass_1(asm): 153 | pasm = [] 154 | constants = set() 155 | for p, l in enumerate(asm): 156 | progress(p, len(asm)-1) 157 | if l.startswith("mov") and "" not in l: 158 | pasm.append("# pass 1 (constants) > " + l) 159 | 160 | tok = l.find(",", l.find(")")) 161 | if tok == -1: 162 | tok = l.find(",") 163 | source = l[l.index(" "):tok].strip() 164 | dest = l[tok+1:].strip() 165 | 166 | # NOTE: requires M/o/Vfuscator to only produce dword constants 167 | if source.startswith("$"): 168 | pasm.append("#constant> " + l) 169 | 170 | # have to jump through some hoops due to as and ld limitations 171 | # on absolutes 172 | c = hashlib.md5(source[1:]).hexdigest() 173 | pasm.append(".section .data\n") 174 | #pasm.append(".ifndef .C%s\n" % c) 175 | if source[1:] not in constants: 176 | pasm.append(".global .C%s\n" % (c)) # split global 177 | pasm.append(".C%s: .long %s\n" % (c, source[1:])) 178 | constants.add(source[1:]) 179 | #pasm.append(".endif\n") 180 | pasm.append(".section .text\n") 181 | pasm.append("movl (.C%s), %%ebp\n" % c) 182 | pasm.append("movl %%ebp, %s\n" % dest) 183 | else: 184 | pasm.append(l) 185 | else: 186 | pasm.append(l) 187 | return pasm 188 | 189 | # pass 2: 190 | # replace all register to register transfers 191 | def pass_2(asm): 192 | pasm=[] 193 | pasm.append(".section .data\n") 194 | pasm.append(".global .r2r\n") # split global 195 | pasm.append(".r2r: .long 0\n") 196 | pasm.append(".section .text\n") 197 | 198 | for p, l in enumerate(asm): 199 | progress(p, len(asm)-1) 200 | if l.startswith("mov") and "" not in l: 201 | pasm.append("# pass 2 (r2r) > " + l) 202 | 203 | tok = l.find(",", l.find(")")) 204 | if tok == -1: 205 | tok = l.find(",") 206 | source = l[l.index(" "):tok].strip() 207 | dest = l[tok+1:].strip() 208 | 209 | if l.startswith("movb"): 210 | s = "b" 211 | elif l.startswith("movw"): 212 | s = "w" 213 | elif l.startswith("movl"): 214 | s = "l" 215 | 216 | if source.startswith("%") and dest.startswith("%"): 217 | pasm.append("mov%s %s, (.r2r)\n" % (s, source)) 218 | pasm.append("mov%s (.r2r), %s\n" % (s, dest)) 219 | else: 220 | pasm.append(l) 221 | 222 | else: 223 | pasm.append(l) 224 | return pasm 225 | 226 | # pass 3: 227 | # pad .data and .bss sections to allow data accesses to extend past boundaries 228 | def pass_3(asm): 229 | pasm=[] 230 | pasm.append("# section padding\n") 231 | pasm.append(".section .data\n") 232 | for i in xrange(0,(XFER_SIZE+1)/4): 233 | pasm.append(".long 0\n") 234 | pasm.append(".section .bss\n") 235 | for i in xrange(0,(XFER_SIZE+1)/4): 236 | pasm.append(".long 0\n") 237 | pasm.append("# end padding\n") 238 | pasm.append("# mov32 shuffle space\n") 239 | pasm.append(".section .data\n") 240 | for i in xrange(0,(XFER_SIZE+1)/4): 241 | pasm.append(".global .s_a%d\n" % i) # split global 242 | pasm.append(".s_a%d: .byte 0\n" % i) 243 | for i in xrange(0,(XFER_SIZE+1)/4): 244 | pasm.append(".global .s_b%d\n" % i) # split global 245 | pasm.append(".s_b%d: .byte 0\n" % i) 246 | for i in xrange(0,(XFER_SIZE+1)/4): 247 | pasm.append(".global .s_c%d\n" % i) # split global 248 | pasm.append(".s_c%d: .byte 0\n" % i) 249 | for i in xrange(0,(XFER_SIZE+1)/4): 250 | pasm.append(".global .r_a%d\n" % i) # split global 251 | pasm.append(".r_a%d: .byte 0\n" % i) 252 | for i in xrange(0,(XFER_SIZE+1)/4): 253 | pasm.append(".global .r_b%d\n" % i) # split global 254 | pasm.append(".r_b%d: .byte 0\n" % i) 255 | for i in xrange(0,(XFER_SIZE+1)/4): 256 | pasm.append(".global .r_c%d\n" % i) # split global 257 | pasm.append(".r_c%d: .byte 0\n" % i) 258 | pasm.append("# end shuffle space\n") 259 | for p, l in enumerate(asm): 260 | progress(p, len(asm)-1) 261 | pasm.append(l) 262 | pasm.append("# section padding\n") 263 | pasm.append(".section .data\n") 264 | for i in xrange(0,(XFER_SIZE+1)/4): 265 | pasm.append(".long 0\n") 266 | pasm.append(".section .bss\n") 267 | for i in xrange(0,(XFER_SIZE+1)/4): 268 | pasm.append(".long 0\n") 269 | pasm.append("# end padding\n") 270 | 271 | return pasm 272 | 273 | # pass 4: 274 | # convert all transfers to 32 bits 275 | def pass_4(asm): 276 | pasm=[] 277 | for p, l in enumerate(asm): 278 | progress(p, len(asm)-1) 279 | if l.startswith("mov") and "" not in l: 280 | pasm.append("# pass 4 (32b) > " + l) 281 | 282 | tok = l.find(",", l.find(")")) 283 | if tok == -1: 284 | tok = l.find(",") 285 | source = l[l.index(" "):tok].strip() 286 | dest = l[tok+1:].strip() 287 | 288 | # warning: ebp used in a previous pass to load immediates. it's 289 | # okay since it was loading 32 bit values, and won't be translated here. 290 | sr = "%ebp" 291 | 292 | if l.startswith("movb"): 293 | if source.startswith("%"): 294 | # r8 -> m8 295 | r32 = "%%e%cx" % source[1] 296 | m = dest[dest.index("(")+1:dest.index(")")] 297 | if not "%" in m: 298 | # "(b)" format 299 | b = m 300 | si = "" 301 | else: 302 | # "b(si)" format 303 | b = dest[:dest.index("(")] 304 | si = "(" + m + ")" 305 | 306 | pasm.append("movl %s, (.s_b0)\n" % r32) 307 | 308 | pasm.append("movl %s%+d%s, %s\n" % (b, -XFER_SIZE, si, sr)) 309 | 310 | if source[2] == 'h': 311 | pasm.append("movl %s, (.s_b0%+d)\n" % (sr, -XFER_SIZE+1)) 312 | pasm.append("movl (.s_b0%+d), %s\n" % (-XFER_SIZE+2, sr)) 313 | elif source[2] == 'l': 314 | pasm.append("movl %s, (.s_b0%+d)\n" % (sr, -XFER_SIZE)) 315 | pasm.append("movl (.s_b0%+d), %s\n" % (-XFER_SIZE+1, sr)) 316 | else: 317 | raise Exception 318 | 319 | pasm.append("movl %s, %s%+d%s\n" % (sr, b, -XFER_SIZE+1, si)) 320 | 321 | else: 322 | # m8 -> r8 323 | r32 = "%%e%cx" % dest[1] 324 | m = source[source.index("(")+1:source.index(")")] 325 | if not "%" in m: 326 | # "(b)" format 327 | b = m 328 | si = "" 329 | else: 330 | # "b(si)" format 331 | b = source[:source.index("(")] 332 | si = "(" + m + ")" 333 | 334 | pasm.append("movl %s, (.r_b0)\n" % r32) 335 | 336 | if dest[2] == 'h': 337 | pasm.append("movl %s%s, %s\n" % (b, si, sr)) 338 | pasm.append("movl %s, (.s_b0+1)\n" % (sr)) 339 | pasm.append("movl (.r_b0+2), %s\n" % (sr)) 340 | pasm.append("movl %s, (.s_b0+2)\n" % (sr)) 341 | pasm.append("movl (.r_b0%+d), %s\n" % (sr, -XFER_SIZE+1)) 342 | pasm.append("movl %s, (.s_b0%+d)\n" % (sr, -XFER_SIZE+1)) 343 | elif dest[2] == 'l': 344 | pasm.append("movl %s%s, %s\n" % (b, si, sr)) 345 | pasm.append("movl %s, (.s_b0)\n" % (sr)) 346 | pasm.append("movl (.r_b0+1), %s\n" % (sr)) 347 | pasm.append("movl %s, (.s_b0+1)\n" % (sr)) 348 | else: 349 | raise Exception 350 | 351 | pasm.append("movl (.s_b0), %s\n" % r32) 352 | 353 | elif l.startswith("movw"): 354 | if source.startswith("%"): 355 | # r16 -> m16 356 | r32 = "%%e%cx" % source[1] 357 | m = dest[dest.index("(")+1:dest.index(")")] 358 | if not "%" in m: 359 | # "(b)" format 360 | b = m 361 | si = "" 362 | else: 363 | # "b(si)" format 364 | b = dest[:dest.index("(")] 365 | si = "(" + m + ")" 366 | 367 | pasm.append("movl %s, (.s_b0)\n" % r32) 368 | 369 | pasm.append("movl %s%+d%s, %s\n" % (b, -XFER_SIZE, si, sr)) 370 | 371 | pasm.append("movl %s, (.s_b0%+d)\n" % (sr, -XFER_SIZE)) 372 | pasm.append("movl (.s_b0%+d), %s\n" % (-XFER_SIZE+2, sr)) 373 | 374 | pasm.append("movl %s, %s%+d%s\n" % (sr, b, -XFER_SIZE+2, si)) 375 | 376 | else: 377 | # m16 -> r16 378 | r32 = "%%e%cx" % dest[1] 379 | m = source[source.index("(")+1:source.index(")")] 380 | if not "%" in m: 381 | # "(b)" format 382 | b = m 383 | si = "" 384 | else: 385 | # "b(si)" format 386 | b = source[:source.index("(")] 387 | si = "(" + m + ")" 388 | 389 | pasm.append("movl %s, (.r_b0)\n" % r32) 390 | 391 | pasm.append("movl %s%s, %s\n" % (b, si, sr)) 392 | pasm.append("movl %s, (.s_b0)\n" % (sr)) 393 | pasm.append("movl (.r_b0+2), %s\n" % (sr)) 394 | pasm.append("movl %s, (.s_b0+2)\n" % (sr)) 395 | 396 | pasm.append("movl (.s_b0), %s\n" % r32) 397 | 398 | elif l.startswith("movl"): 399 | pasm.append(l) 400 | 401 | else: 402 | pasm.append(l) 403 | 404 | return pasm 405 | 406 | # pass 5: convert all addressing to base + offset addressing 407 | # e.g.: [eax+4*ebx+12345678] -> [ecx+12345678] 408 | # This may not be the actual desired addressing mode, but it is much easier to 409 | # translate to other modes after initially converted to base/offset 410 | def pass_5(asm): 411 | pasm=[] 412 | pasm.append(".section .data\n") 413 | pasm.append(".global .eax\n") # split global 414 | pasm.append(".eax: .long 0\n") 415 | pasm.append(".global .ebx\n") # split global 416 | pasm.append(".ebx: .long 0\n") 417 | pasm.append(".global .ecx\n") # split global 418 | pasm.append(".ecx: .long 0\n") 419 | pasm.append(".global .edx\n") # split global 420 | pasm.append(".edx: .long 0\n") 421 | pasm.append(".global .esi\n") # split global 422 | pasm.append(".esi: .long 0\n") 423 | pasm.append(".global .edi\n") # split global 424 | pasm.append(".edi: .long 0\n") 425 | pasm.append(".global .ebp\n") # split global 426 | pasm.append(".ebp: .long 0\n") 427 | pasm.append(".global .esp\n") # split global 428 | pasm.append(".esp: .long 0\n") 429 | pasm.append(".global .zero\n") # split global 430 | pasm.append(".zero: .long 0\n") 431 | pasm.append(".long 0\n") 432 | pasm.append(".global .chop\n") # split global 433 | pasm.append(".chop: .long 0\n") 434 | pasm.append(".long 0\n") 435 | pasm.append(".global .sum_x\n") # split global 436 | pasm.append(".sum_x: .long 0\n") 437 | 438 | for i in (0,1,2,3): 439 | pasm.append(".global .ind%dl\n" % i) # split global 440 | pasm.append(".ind%dl: .long 0\n" % i) 441 | pasm.append(".global .ind%dh\n" % i) # split global 442 | pasm.append(".ind%dh: .long 0\n" % i) 443 | 444 | pasm.append(".long 0\n") 445 | pasm.append(".global .oraddr\n") # split global 446 | pasm.append(".oraddr: .long 0\n") 447 | pasm.append(".long 0\n") 448 | 449 | pasm.append(".long 0\n") 450 | pasm.append(".global .orresult\n") # split global 451 | pasm.append(".orresult: .long 0\n") 452 | pasm.append(".long 0\n") 453 | 454 | for k in (0,1,2,3): 455 | pasm.append(".global .scale%dl\n" % (2**k)) # split global 456 | pasm.append(".scale%dl:\n" % (2**k)) 457 | for i in xrange(0,256): 458 | pasm.append(".byte 0x%02x\n" % ((i<>8)) 463 | 464 | pasm.append(".global .riscor\n") # split global 465 | pasm.append(".riscor:\n") 466 | for i in xrange(0,0x10000): 467 | pasm.append(".byte 0x%02x\n" % ((i&0xff)|((i&0xff00)>>8))) 468 | 469 | pasm.append(".long 0\n") 470 | pasm.append(".global .sumaddr\n") # split global 471 | pasm.append(".sumaddr: .long 0\n") 472 | pasm.append(".long 0\n") 473 | 474 | pasm.append(".long 0\n") 475 | pasm.append(".global .sumcarry\n") # split global 476 | pasm.append(".sumcarry: .long 0\n") 477 | pasm.append(".long 0\n") 478 | 479 | pasm.append(".long 0\n") 480 | pasm.append(".global .sumresult\n") # split global 481 | pasm.append(".sumresult: .long 0\n") 482 | pasm.append(".long 0\n") 483 | 484 | for i in (0,1,2,3): 485 | pasm.append(".global .sum%dl\n" % i) # split global 486 | pasm.append(".sum%dl: .long 0, 0\n" % i) 487 | pasm.append(".global .sum%dh\n" % i) # split global 488 | pasm.append(".sum%dh: .long 0, 0\n" % i) 489 | 490 | pasm.append(".global .riscaddl\n") # split global 491 | pasm.append(".riscaddl:\n") 492 | for i in xrange(0,0x20000): 493 | pasm.append(".byte 0x%02x\n" % \ 494 | (((i&0xff)+((i&0xff00)>>8)+((i&0x10000)>>16))&0xff)) 495 | pasm.append(".global .riscaddh\n") # split global 496 | pasm.append(".riscaddh:\n") 497 | for i in xrange(0,0x20000): 498 | pasm.append(".byte 0x%02x\n" % \ 499 | (((i&0xff)+((i&0xff00)>>8)+((i&0x10000)>>16))>>8)) 500 | 501 | pasm.append(".section .text\n") 502 | 503 | for p, l in enumerate(asm): 504 | progress(p, len(asm)-1) 505 | if l.startswith("mov") and "" not in l: 506 | pasm.append("# pass 5 (risc) > " + l) 507 | 508 | match = re.search(r'^mov([bwl])\s+(.*)\s*,\s*([^#]*).*\n$', l) 509 | 510 | (size, source, dest) = match.groups() 511 | 512 | if ismem(source): 513 | (offset, base, index, scale) = decompose(source) 514 | else: 515 | (offset, base, index, scale) = decompose(dest) 516 | 517 | pasm.append("movl .zero(%edi), %esi\n") 518 | 519 | if index and scale: 520 | for b in ('l','h'): 521 | for i in (0,1,2,3): 522 | # get byte 523 | pasm.append("movl .%s(%%edi), %%esi\n" % index[1:]) 524 | pasm.append("movl %esi, .chop(%edi)\n") 525 | pasm.append("movl .zero(%edi), %esi\n") 526 | pasm.append("movl %%esi, .chop+%d(%%edi)\n" % (i+1)) 527 | pasm.append("movl .chop+%d(%%edi), %%esi\n" % (i)) 528 | 529 | # shift 530 | pasm.append("movl .scale%s%c(%%esi), %%esi\n" % (scale, b)) 531 | pasm.append("movl %esi, .chop(%edi)\n") 532 | pasm.append("movl .zero(%edi), %esi\n") 533 | pasm.append("movl %esi, .chop+1(%edi)\n") 534 | pasm.append("movl .chop(%edi), %esi\n") 535 | 536 | # save 537 | pasm.append("movl %%esi, .ind%d%c(%%edi)\n" % (i, b)) 538 | 539 | pasm.append("movl .ind0l(%edi), %esi\n") 540 | pasm.append("movl %esi, .orresult(%edi)\n") 541 | for i in (1,2,3): 542 | pasm.append("movl .ind%dh(%%edi), %%esi\n" % (i-1)) 543 | pasm.append("movl %esi, .oraddr(%edi)\n") 544 | pasm.append("movl .ind%dl(%%edi), %%esi\n" % (i)) 545 | pasm.append("movl %esi, .oraddr+1(%edi)\n") 546 | pasm.append("movl .oraddr(%edi), %esi\n") 547 | pasm.append("movl .riscor(%esi), %esi\n") 548 | pasm.append("movl %%esi, .orresult+%d(%%edi)\n" % i) 549 | 550 | pasm.append("movl .orresult(%edi), %esi\n") 551 | 552 | elif index: 553 | pasm.append("movl .%s(%%edi), %s\n" % (index[1:], "%esi")) 554 | 555 | if base and index: 556 | pasm.append("movl %esi, .sum_x(%edi)\n") 557 | 558 | pasm.append("movl .zero(%edi), %esi\n") 559 | pasm.append("movl %esi, .sumcarry(%edi)\n") 560 | 561 | for i in (0,1,2,3): 562 | # merge 563 | pasm.append("movl .%s(%%edi), %%esi\n" % base[1:]) 564 | pasm.append("movl %esi, .chop(%edi)\n") 565 | pasm.append("movl .chop+%d(%%edi), %%esi\n" % (i)) 566 | pasm.append("movl %esi, .sumaddr(%edi)\n") 567 | 568 | pasm.append("movl .sum_x+%d(%%edi), %%esi\n" % (i)) 569 | pasm.append("movl %esi, .sumaddr+1(%edi)\n") 570 | 571 | pasm.append("movl .sumcarry(%edi), %esi\n") 572 | pasm.append("movl %esi, .sumaddr+2(%edi)\n") 573 | 574 | # sum 575 | pasm.append("movl .sumaddr(%edi), %esi\n") 576 | pasm.append("movl .riscaddl(%esi), %esi\n") 577 | pasm.append("movl %%esi, .sumresult+%d(%%edi)\n" % i) 578 | 579 | pasm.append("movl .sumaddr(%edi), %esi\n") 580 | pasm.append("movl .riscaddh(%esi), %esi\n") 581 | pasm.append("movl %esi, .sumcarry(%edi)\n") 582 | pasm.append("movl .zero(%edi), %esi\n") 583 | pasm.append("movl %esi, .sumcarry+1(%edi)\n") 584 | 585 | pasm.append("movl .sumresult(%edi), %esi\n") 586 | 587 | elif base: 588 | pasm.append("movl .%s(%%edi), %%esi\n" % base[1:]) 589 | 590 | if ismem(source): 591 | pasm.append("movl.d32 %s(%s), %s\n" % (offset, "%esi", "%esi")) 592 | pasm.append("movl %%esi, .%s(%%edi)\n" % dest[1:]) 593 | 594 | if "" in l: 595 | pasm.append("# \n") 596 | pasm.append("movl .%s(%%edi), %s\n" % (dest[1:], dest)) 597 | 598 | else: 599 | if "" in l: 600 | pasm.append("# \n") 601 | pasm.append("movl %s, .%s(%%edi)\n" % (source, source[1:])) 602 | 603 | pasm.append("movl .%s(%%edi), %%edx\n" % (source[1:])) 604 | pasm.append("movl.d32 %s, %s(%s)\n" % ("%edx", offset, "%esi")) 605 | 606 | else: 607 | pasm.append(l) 608 | 609 | return pasm 610 | 611 | # pass 6: 612 | # - alternate reads and writes, standardize instruction format 613 | def pass_6(asm): 614 | pasm=[] 615 | pasm.append(".section .data\n") 616 | pasm.append(".global .scratch_rw\n") # split global 617 | pasm.append(".scratch_rw: .long 0\n") 618 | pasm.append(".section .text\n") 619 | last_write = False 620 | 621 | for p, l in enumerate(asm): 622 | progress(p, len(asm)-1) 623 | if l.startswith("mov") and "" not in l: 624 | pasm.append("# pass 6 (alternate) > " + l) 625 | 626 | match = re.search(r'^movl[^\s]*\s+(.*)\s*,\s*([^#]*).*\n$', l) 627 | 628 | (source, dest) = match.groups() 629 | 630 | if ismem(source): 631 | (offset, base, index, scale) = decompose(source) 632 | else: 633 | (offset, base, index, scale) = decompose(dest) 634 | 635 | assert index == "" 636 | assert scale == "" 637 | 638 | if offset == "": 639 | offset = "0" 640 | base = "(" + base + ")" 641 | if ismem(source): 642 | if not last_write: 643 | pasm.append("movl.d32 %edi, .scratch_rw(%edi)\n") 644 | pasm.append("movl.d32 %s%s, %s\n" % (offset, base, dest)) 645 | last_write = False 646 | else: 647 | if last_write: 648 | pasm.append("movl.d32 .scratch_rw(%edi), %edi\n") 649 | pasm.append("movl.d32 %s, %s%s\n" % (source, offset, base)) 650 | last_write = True 651 | else: 652 | pasm.append(l) 653 | 654 | if last_write: 655 | pasm.append("movl.d32 .scratch_rw(%edi), %edi\n") 656 | 657 | return pasm 658 | 659 | def reduce(s, prologue): 660 | pasm = [] 661 | 662 | # (hack) keep data starting locations consistent to ensure identical 663 | # addresses in instruction stream 664 | # (see note on gnu as quirk later) 665 | # (semicolon hack ensures alignment and section directives don't get split 666 | # across files by break_write) 667 | pasm.append(".section .data ; .balign 0x10000\n") 668 | 669 | # (hack) keep text starting locations consistent to ensure identical 670 | # addresses in instruction stream 671 | # (see note on gnu as quirk later) 672 | # (semicolon hack ensures alignment and section directives don't get split 673 | # across files by break_write) 674 | pasm.append(".section .text ; .balign 0x10000\n") 675 | 676 | pasm.append("### prologue ###\n") 677 | for l in prologue: 678 | pasm.append(l) 679 | pasm.append("### end prologue ###\n") 680 | 681 | # patch up issue with mov_extern that i'm too lazy to fix 682 | # (assumes compiling with -Wf--no-mov-extern) 683 | # (this is for the old version using fault-linking) 684 | # also fixes issue when manually omitting crtf during linking 685 | pasm.append(".global dispatch\n") 686 | pasm.append("dispatch:\n") 687 | 688 | # virtual registers and selectors 689 | v_regs = ["eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp"] 690 | pasm.append(".section .data\n") 691 | for r in v_regs: 692 | pasm.append(".global .v_%s\n" % r) # split global 693 | pasm.append(".v_%s: .long 0\n" % r) 694 | pasm.append(".global .v_reg\n") # split global 695 | pasm.append(".v_reg: .long %s\n" % ",".join(".v_" + s for s in v_regs)) 696 | # selector references, allows unconditional dereference in sim loop 697 | for r in v_regs: 698 | pasm.append(".global .vv_%s\n" % r) # split global 699 | pasm.append(".vv_%s: .long .v_%s\n" % (r, r)) 700 | pasm.append(".global .vv_reg\n") # split global 701 | pasm.append(".vv_reg: .long %s\n" % ",".join(".vv_" + s for s in v_regs)) 702 | pasm.append(".section .text\n") 703 | 704 | operands = [] 705 | returns = [] 706 | mcount = 0 707 | 708 | operands.append(".global .a_0") # split global 709 | operands.append(".a_0:") 710 | 711 | last_branch_index = -1 712 | 713 | for p, l in enumerate(asm): 714 | progress(p, len(asm)-1) 715 | if l.startswith("mov") and "" not in l: 716 | pasm.append("#S> " + l) 717 | match = re.search(r'^movl[^\s]*\s+(.*)\s*,\s*([^#]*).*\n$', l) 718 | 719 | (source, dest) = match.groups() 720 | 721 | if ismem(source): 722 | (offset, base, index, scale) = decompose(source) 723 | else: 724 | (offset, base, index, scale) = decompose(dest) 725 | 726 | assert index == "" 727 | assert scale == "" 728 | 729 | if ismem(source): 730 | # read 731 | operands.append("# %s (%d)" % (l.strip(), mcount)) 732 | operands.append(".v_" + base[1:]) 733 | operands.append(offset) 734 | operands.append(".vv_" + dest[1:]) 735 | operands.append("0") 736 | else: 737 | # write 738 | operands.append("# %s (%d)" % (l.strip(), mcount)) 739 | operands.append(".vv_" + source[1:]) 740 | operands.append("0") 741 | operands.append(".v_" + base[1:]) 742 | operands.append(offset) 743 | operands.append(".loop") 744 | operands.append(".loop") 745 | last_branch_index = len(operands) - 1 746 | mcount = mcount + 1 747 | operands.append(".a_" + str(mcount)) 748 | operands.append(".global .a_" + str(mcount)) # split global 749 | operands.append(".a_" + str(mcount) + ":") 750 | elif l.startswith(".LCI") or "" in l: 751 | # internal label (branching) 752 | operands.append(".global " + l.split(":")[0]) # split global 753 | operands.append(l) 754 | elif l.startswith(".LCE") or "" in l: 755 | # external label (return address) 756 | returns.append(".global " + l.split(":")[0] + "\n") # split global 757 | returns.append(l) 758 | elif l.startswith(".LCS") or "" in l: 759 | # label used by symbol 760 | pasm.append(".global " + l.split(":")[0] + "\n") # split global 761 | pasm.append(l) 762 | elif l.startswith(".size"): 763 | # discard size directives 764 | pass 765 | elif l.startswith("cmp"): 766 | # discard comparisons (handled by je) 767 | pass 768 | elif l.startswith("je"): 769 | # accumulate non-movfuscated calls 770 | operands[last_branch_index] = l[3:] + " # target" 771 | else: 772 | pasm.append(l) 773 | 774 | # so hacky, fix this... 775 | #operands.remove(".a_" + str(mcount) +":") 776 | #operands = [o.replace(".a_" + str(mcount) , ".a_0") for o in operands] 777 | assert operands[last_branch_index+1] == ".a_" + str(mcount) 778 | assert operands[last_branch_index+2] == ".global .a_" + str(mcount) 779 | assert operands[last_branch_index+3] == ".a_" + str(mcount) + ":" 780 | operands[last_branch_index+1] = ".a_0" 781 | #del operands[last_branch_index+2:last_branch_index+4] 782 | del operands[last_branch_index+2] 783 | del operands[last_branch_index+2] 784 | 785 | pasm.append(".section .text\n") 786 | pasm.append("movl $.operands, %esi\n") 787 | 788 | # version for linking by faults 789 | ''' 790 | pasm.append(".loop:\n") 791 | 792 | pasm.append("movl %eax, .v_eax\n") 793 | pasm.append("movl .v_esp, %esp\n") 794 | 795 | pasm.append("movl 0(%esi), %ebx\n") 796 | pasm.append("movl (%ebx), %ebx\n") 797 | pasm.append("addl 4(%esi), %ebx\n") 798 | pasm.append("movl (%ebx), %ebx\n") 799 | 800 | for r in returns: 801 | pasm.append(r) 802 | 803 | pasm.append("movl 8(%esi), %edx\n") 804 | pasm.append("movl (%edx), %edx\n") 805 | pasm.append("addl 12(%esi), %edx\n") 806 | pasm.append("movl %ebx, (%edx)\n") 807 | pasm.append("movl 24(%esi), %esi\n") 808 | 809 | pasm.append("jmp .loop\n") 810 | ''' 811 | 812 | # version for linking by jumps 813 | # (simple version) 814 | ''' 815 | pasm.append("movl %eax, .v_eax\n") 816 | 817 | pasm.append("movl 0(%esi), %ebx\n") 818 | pasm.append("movl (%ebx), %ebx\n") 819 | pasm.append("addl 4(%esi), %ebx\n") 820 | pasm.append("movl (%ebx), %ebx\n") 821 | 822 | pasm.append("movl 8(%esi), %edx\n") 823 | pasm.append("movl (%edx), %edx\n") 824 | pasm.append("addl 12(%esi), %edx\n") 825 | pasm.append("movl %ebx, (%edx)\n") 826 | 827 | pasm.append("movl (on), %edx\n") 828 | pasm.append("shl $2, %edx\n") 829 | pasm.append("addl %esi, %edx\n") 830 | pasm.append("movl 16(%edx), %edx\n") 831 | 832 | pasm.append("movl 24(%esi), %esi\n") 833 | 834 | pasm.append("movl .v_esp, %esp\n") 835 | pasm.append("jmp *%edx\n") 836 | ''' 837 | 838 | # version for linking by jumps 839 | # (reduced version) 840 | for r in returns: 841 | pasm.append(r) 842 | 843 | pasm.append(".global .loop\n") # split global 844 | pasm.append(".loop:\n") 845 | 846 | pasm.append("movl 24(%esi), %esi\n") 847 | 848 | pasm.append("movl %eax, .v_eax\n") 849 | 850 | pasm.append("movl 0(%esi), %ebx\n") 851 | pasm.append("movl (%ebx), %ebx\n") 852 | pasm.append("addl 4(%esi), %ebx\n") 853 | pasm.append("movl (%ebx), %ebx\n") 854 | 855 | pasm.append("movl 8(%esi), %edx\n") 856 | pasm.append("movl (%edx), %edx\n") 857 | pasm.append("addl 12(%esi), %edx\n") 858 | pasm.append("movl %ebx, (%edx)\n") 859 | 860 | pasm.append("movl (on), %edx\n") 861 | 862 | pasm.append("movl .v_esp, %esp\n") 863 | pasm.append("jmp *16(%esi,%edx,4)\n") 864 | 865 | pasm.append(".section .data\n") 866 | 867 | # (hack) keep data starting locations consistent to ensure identical 868 | # addresses in instruction stream 869 | # (see note on gnu as quirk later) 870 | # (semicolon hack ensures alignment and section directives don't get split 871 | # across files by break_write) 872 | pasm.append(".section .data ; .balign 0x10000\n") 873 | 874 | # allow first chunk skip 875 | pasm.append(".long .operands\n") 876 | pasm.append(".long .operands\n") 877 | pasm.append(".long .operands\n") 878 | pasm.append(".long .operands\n") 879 | pasm.append(".long .operands\n") 880 | pasm.append(".long .operands\n") 881 | 882 | pasm.append(".global .operands\n") 883 | pasm.append(".operands:\n") 884 | 885 | for p, l in enumerate(operands): 886 | progress(p, len(operands)-1) 887 | if l.startswith("#"): 888 | pasm.append(l + "\n") 889 | elif l.startswith(".glob"): 890 | pasm.append(l + "\n") 891 | elif ":" in l: 892 | pasm.append(l + "\n") 893 | else: 894 | pasm.append(".long %s\n" % l) 895 | 896 | return pasm 897 | 898 | if subprocess.call("type movcc", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) != 0: 899 | print "Reduction requires installing the M/o/Vfuscator." 900 | print "" 901 | print "git clone https://github.com/xoreaxeaxeax/movfuscator" 902 | print "cd movfuscator" 903 | print "./build.sh" 904 | print "sudo ./install.sh" 905 | exit(1) 906 | 907 | mov_install=subprocess.Popen("readlink -f `which movcc`", shell=True, stdout=subprocess.PIPE).communicate()[0] 908 | mov_dir=os.path.dirname(mov_install) 909 | 910 | c_file=sys.argv[1] 911 | e_file=os.path.splitext(c_file)[0] 912 | s_file=e_file+".s" 913 | o_file=e_file+".o" 914 | linker_args=sys.argv[2:] 915 | 916 | print "compiling..." 917 | command=\ 918 | "movcc "\ 919 | "%s "\ 920 | "-S "\ 921 | "-Wf--crt0 "\ 922 | "-Wf--no-mov-loop "\ 923 | "-Wf--no-mov-extern "\ 924 | "-Wf--q "\ 925 | "-o %s"\ 926 | % (c_file, s_file) 927 | os.system(command) 928 | print "...done" 929 | 930 | # reduce 931 | print "reducing... " 932 | 933 | print "\tloading... " 934 | asm=load(s_file) 935 | 936 | sys.stdout.write("\tprologue... ") 937 | [asm,prologue]=remove_prologue(asm) 938 | sys.stdout.write("\n") 939 | 940 | sys.stdout.write("\tpass 1... ") 941 | asm=pass_1(asm) 942 | sys.stdout.write("\n") 943 | 944 | sys.stdout.write("\tpass 2... ") 945 | asm=pass_2(asm) 946 | sys.stdout.write("\n") 947 | 948 | sys.stdout.write("\tpass 3... ") 949 | asm=pass_3(asm) 950 | sys.stdout.write("\n") 951 | 952 | sys.stdout.write("\tpass 4... ") 953 | asm=pass_4(asm) 954 | sys.stdout.write("\n") 955 | 956 | sys.stdout.write("\tpass 5... ") 957 | asm=pass_5(asm) 958 | sys.stdout.write("\n") 959 | 960 | sys.stdout.write("\tpass 6... ") 961 | asm=pass_6(asm) 962 | sys.stdout.write("\n") 963 | 964 | sys.stdout.write("\treduce... ") 965 | asm=reduce(asm, prologue) 966 | sys.stdout.write("\n") 967 | 968 | sys.stdout.write("\twrite... ") 969 | s_files=break_write(s_file, asm) 970 | sys.stdout.write("\n") 971 | 972 | # assemble 973 | o_files = [] 974 | sys.stdout.write("\tassemble... ") 975 | for p, l in enumerate(s_files): 976 | progress(p, len(s_files)-1) 977 | o = "%s%03d" % (o_file, p) 978 | o_files.append(o) 979 | command="as --32 %s -o %s" % (l, o) 980 | os.system(command) 981 | sys.stdout.write("\n") 982 | 983 | # link 984 | sys.stdout.write("\tlink... ") 985 | sys.stdout.flush() 986 | command=\ 987 | "ld -melf_i386 -dynamic-linker /lib/ld-linux.so.2 "\ 988 | "-L %s/ "\ 989 | "-L %s/gcc/32/ "\ 990 | "-lgcc "\ 991 | "-lc "\ 992 | "-lm "\ 993 | "-s "\ 994 | "%s/crtd.o "\ 995 | "%s "\ 996 | "%s "\ 997 | "-o %s"\ 998 | % (mov_dir, mov_dir, mov_dir, " ".join(linker_args), " ".join(o_files), e_file) 999 | os.system(command) 1000 | sys.stdout.write("\n") 1001 | 1002 | print "...done " 1003 | --------------------------------------------------------------------------------