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 <stdlib.h> |

20 | #include <memory.h> |

21 | #include "aes.h" |

22 | |

23 | #include <stdio.h> |

24 | #include <string.h> |

25 | |

26 | /****************************** MACROS ******************************/ |

27 | // The least significant byte of the word is rotated to the end. |

28 | #define KE_ROTWORD(x) (((x) << 8) | ((x) >> 24)) |

29 | |

30 | #define TRUE 1 |

31 | #define FALSE 0 |

32 | |

33 | /**************************** DATA TYPES ****************************/ |

34 | #define AES_128_ROUNDS 10 |

35 | #define AES_192_ROUNDS 12 |

36 | #define AES_256_ROUNDS 14 |

37 | |

38 | /*********************** FUNCTION DECLARATIONS **********************/ |

39 | void ccm_prepare_first_ctr_blk(BYTE counter[], const BYTE nonce[], int nonce_len, int payload_len_store_size); |

40 | 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); |

41 | void ccm_format_assoc_data(BYTE buf[], int *end_of_buf, const BYTE assoc[], int assoc_len); |

42 | void ccm_format_payload_data(BYTE buf[], int *end_of_buf, const BYTE payload[], int payload_len); |

43 | |

44 | /**************************** VARIABLES *****************************/ |

45 | // This is the specified AES SBox. To look up a substitution value, put the first |

46 | // nibble in the first index (row) and the second nibble in the second index (column). |

47 | static const BYTE aes_sbox[16][16] = { |

48 | {0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76}, |

49 | {0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0}, |

50 | {0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15}, |

51 | {0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75}, |

52 | {0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84}, |

53 | {0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF}, |

54 | {0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8}, |

55 | {0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2}, |

56 | {0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73}, |

57 | {0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB}, |

58 | {0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79}, |

59 | {0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08}, |

60 | {0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A}, |

61 | {0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E}, |

62 | {0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF}, |

63 | {0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16} |

64 | }; |

65 | |

66 | static const BYTE aes_invsbox[16][16] = { |

67 | {0x52,0x09,0x6A,0xD5,0x30,0x36,0xA5,0x38,0xBF,0x40,0xA3,0x9E,0x81,0xF3,0xD7,0xFB}, |

68 | {0x7C,0xE3,0x39,0x82,0x9B,0x2F,0xFF,0x87,0x34,0x8E,0x43,0x44,0xC4,0xDE,0xE9,0xCB}, |

69 | {0x54,0x7B,0x94,0x32,0xA6,0xC2,0x23,0x3D,0xEE,0x4C,0x95,0x0B,0x42,0xFA,0xC3,0x4E}, |

70 | {0x08,0x2E,0xA1,0x66,0x28,0xD9,0x24,0xB2,0x76,0x5B,0xA2,0x49,0x6D,0x8B,0xD1,0x25}, |

71 | {0x72,0xF8,0xF6,0x64,0x86,0x68,0x98,0x16,0xD4,0xA4,0x5C,0xCC,0x5D,0x65,0xB6,0x92}, |

72 | {0x6C,0x70,0x48,0x50,0xFD,0xED,0xB9,0xDA,0x5E,0x15,0x46,0x57,0xA7,0x8D,0x9D,0x84}, |

73 | {0x90,0xD8,0xAB,0x00,0x8C,0xBC,0xD3,0x0A,0xF7,0xE4,0x58,0x05,0xB8,0xB3,0x45,0x06}, |

74 | {0xD0,0x2C,0x1E,0x8F,0xCA,0x3F,0x0F,0x02,0xC1,0xAF,0xBD,0x03,0x01,0x13,0x8A,0x6B}, |

75 | {0x3A,0x91,0x11,0x41,0x4F,0x67,0xDC,0xEA,0x97,0xF2,0xCF,0xCE,0xF0,0xB4,0xE6,0x73}, |

76 | {0x96,0xAC,0x74,0x22,0xE7,0xAD,0x35,0x85,0xE2,0xF9,0x37,0xE8,0x1C,0x75,0xDF,0x6E}, |

77 | {0x47,0xF1,0x1A,0x71,0x1D,0x29,0xC5,0x89,0x6F,0xB7,0x62,0x0E,0xAA,0x18,0xBE,0x1B}, |

78 | {0xFC,0x56,0x3E,0x4B,0xC6,0xD2,0x79,0x20,0x9A,0xDB,0xC0,0xFE,0x78,0xCD,0x5A,0xF4}, |

79 | {0x1F,0xDD,0xA8,0x33,0x88,0x07,0xC7,0x31,0xB1,0x12,0x10,0x59,0x27,0x80,0xEC,0x5F}, |

80 | {0x60,0x51,0x7F,0xA9,0x19,0xB5,0x4A,0x0D,0x2D,0xE5,0x7A,0x9F,0x93,0xC9,0x9C,0xEF}, |

81 | {0xA0,0xE0,0x3B,0x4D,0xAE,0x2A,0xF5,0xB0,0xC8,0xEB,0xBB,0x3C,0x83,0x53,0x99,0x61}, |

82 | {0x17,0x2B,0x04,0x7E,0xBA,0x77,0xD6,0x26,0xE1,0x69,0x14,0x63,0x55,0x21,0x0C,0x7D} |

83 | }; |

84 | |

85 | // This table stores pre-calculated values for all possible GF(2^8) calculations.This |

86 | // table is only used by the (Inv)MixColumns steps. |

87 | // USAGE: The second index (column) is the coefficient of multiplication. Only 7 different |

88 | // coefficients are used: 0x01, 0x02, 0x03, 0x09, 0x0b, 0x0d, 0x0e, but multiplication by |

89 | // 1 is negligible leaving only 6 coefficients. Each column of the table is devoted to one |

90 | // of these coefficients, in the ascending order of value, from values 0x00 to 0xFF. |

91 | static const BYTE gf_mul[256][6] = { |

92 | {0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x03,0x09,0x0b,0x0d,0x0e}, |

93 | {0x04,0x06,0x12,0x16,0x1a,0x1c},{0x06,0x05,0x1b,0x1d,0x17,0x12}, |

94 | {0x08,0x0c,0x24,0x2c,0x34,0x38},{0x0a,0x0f,0x2d,0x27,0x39,0x36}, |

95 | {0x0c,0x0a,0x36,0x3a,0x2e,0x24},{0x0e,0x09,0x3f,0x31,0x23,0x2a}, |

96 | {0x10,0x18,0x48,0x58,0x68,0x70},{0x12,0x1b,0x41,0x53,0x65,0x7e}, |

97 | {0x14,0x1e,0x5a,0x4e,0x72,0x6c},{0x16,0x1d,0x53,0x45,0x7f,0x62}, |

98 | {0x18,0x14,0x6c,0x74,0x5c,0x48},{0x1a,0x17,0x65,0x7f,0x51,0x46}, |

99 | {0x1c,0x12,0x7e,0x62,0x46,0x54},{0x1e,0x11,0x77,0x69,0x4b,0x5a}, |

100 | {0x20,0x30,0x90,0xb0,0xd0,0xe0},{0x22,0x33,0x99,0xbb,0xdd,0xee}, |

101 | {0x24,0x36,0x82,0xa6,0xca,0xfc},{0x26,0x35,0x8b,0xad,0xc7,0xf2}, |

102 | {0x28,0x3c,0xb4,0x9c,0xe4,0xd8},{0x2a,0x3f,0xbd,0x97,0xe9,0xd6}, |

103 | {0x2c,0x3a,0xa6,0x8a,0xfe,0xc4},{0x2e,0x39,0xaf,0x81,0xf3,0xca}, |

104 | {0x30,0x28,0xd8,0xe8,0xb8,0x90},{0x32,0x2b,0xd1,0xe3,0xb5,0x9e}, |

105 | {0x34,0x2e,0xca,0xfe,0xa2,0x8c},{0x36,0x2d,0xc3,0xf5,0xaf,0x82}, |

106 | {0x38,0x24,0xfc,0xc4,0x8c,0xa8},{0x3a,0x27,0xf5,0xcf,0x81,0xa6}, |

107 | {0x3c,0x22,0xee,0xd2,0x96,0xb4},{0x3e,0x21,0xe7,0xd9,0x9b,0xba}, |

108 | {0x40,0x60,0x3b,0x7b,0xbb,0xdb},{0x42,0x63,0x32,0x70,0xb6,0xd5}, |

109 | {0x44,0x66,0x29,0x6d,0xa1,0xc7},{0x46,0x65,0x20,0x66,0xac,0xc9}, |

110 | {0x48,0x6c,0x1f,0x57,0x8f,0xe3},{0x4a,0x6f,0x16,0x5c,0x82,0xed}, |

111 | {0x4c,0x6a,0x0d,0x41,0x95,0xff},{0x4e,0x69,0x04,0x4a,0x98,0xf1}, |

112 | {0x50,0x78,0x73,0x23,0xd3,0xab},{0x52,0x7b,0x7a,0x28,0xde,0xa5}, |

113 | {0x54,0x7e,0x61,0x35,0xc9,0xb7},{0x56,0x7d,0x68,0x3e,0xc4,0xb9}, |

114 | {0x58,0x74,0x57,0x0f,0xe7,0x93},{0x5a,0x77,0x5e,0x04,0xea,0x9d}, |

115 | {0x5c,0x72,0x45,0x19,0xfd,0x8f},{0x5e,0x71,0x4c,0x12,0xf0,0x81}, |

116 | {0x60,0x50,0xab,0xcb,0x6b,0x3b},{0x62,0x53,0xa2,0xc0,0x66,0x35}, |

117 | {0x64,0x56,0xb9,0xdd,0x71,0x27},{0x66,0x55,0xb0,0xd6,0x7c,0x29}, |

118 | {0x68,0x5c,0x8f,0xe7,0x5f,0x03},{0x6a,0x5f,0x86,0xec,0x52,0x0d}, |

119 | {0x6c,0x5a,0x9d,0xf1,0x45,0x1f},{0x6e,0x59,0x94,0xfa,0x48,0x11}, |

120 | {0x70,0x48,0xe3,0x93,0x03,0x4b},{0x72,0x4b,0xea,0x98,0x0e,0x45}, |

121 | {0x74,0x4e,0xf1,0x85,0x19,0x57},{0x76,0x4d,0xf8,0x8e,0x14,0x59}, |

122 | {0x78,0x44,0xc7,0xbf,0x37,0x73},{0x7a,0x47,0xce,0xb4,0x3a,0x7d}, |

123 | {0x7c,0x42,0xd5,0xa9,0x2d,0x6f},{0x7e,0x41,0xdc,0xa2,0x20,0x61}, |

124 | {0x80,0xc0,0x76,0xf6,0x6d,0xad},{0x82,0xc3,0x7f,0xfd,0x60,0xa3}, |

125 | {0x84,0xc6,0x64,0xe0,0x77,0xb1},{0x86,0xc5,0x6d,0xeb,0x7a,0xbf}, |

126 | {0x88,0xcc,0x52,0xda,0x59,0x95},{0x8a,0xcf,0x5b,0xd1,0x54,0x9b}, |

127 | {0x8c,0xca,0x40,0xcc,0x43,0x89},{0x8e,0xc9,0x49,0xc7,0x4e,0x87}, |

128 | {0x90,0xd8,0x3e,0xae,0x05,0xdd},{0x92,0xdb,0x37,0xa5,0x08,0xd3}, |

129 | {0x94,0xde,0x2c,0xb8,0x1f,0xc1},{0x96,0xdd,0x25,0xb3,0x12,0xcf}, |

130 | {0x98,0xd4,0x1a,0x82,0x31,0xe5},{0x9a,0xd7,0x13,0x89,0x3c,0xeb}, |

131 | {0x9c,0xd2,0x08,0x94,0x2b,0xf9},{0x9e,0xd1,0x01,0x9f,0x26,0xf7}, |

132 | {0xa0,0xf0,0xe6,0x46,0xbd,0x4d},{0xa2,0xf3,0xef,0x4d,0xb0,0x43}, |

133 | {0xa4,0xf6,0xf4,0x50,0xa7,0x51},{0xa6,0xf5,0xfd,0x5b,0xaa,0x5f}, |

134 | {0xa8,0xfc,0xc2,0x6a,0x89,0x75},{0xaa,0xff,0xcb,0x61,0x84,0x7b}, |

135 | {0xac,0xfa,0xd0,0x7c,0x93,0x69},{0xae,0xf9,0xd9,0x77,0x9e,0x67}, |

136 | {0xb0,0xe8,0xae,0x1e,0xd5,0x3d},{0xb2,0xeb,0xa7,0x15,0xd8,0x33}, |

137 | {0xb4,0xee,0xbc,0x08,0xcf,0x21},{0xb6,0xed,0xb5,0x03,0xc2,0x2f}, |

138 | {0xb8,0xe4,0x8a,0x32,0xe1,0x05},{0xba,0xe7,0x83,0x39,0xec,0x0b}, |

139 | {0xbc,0xe2,0x98,0x24,0xfb,0x19},{0xbe,0xe1,0x91,0x2f,0xf6,0x17}, |

140 | {0xc0,0xa0,0x4d,0x8d,0xd6,0x76},{0xc2,0xa3,0x44,0x86,0xdb,0x78}, |

141 | {0xc4,0xa6,0x5f,0x9b,0xcc,0x6a},{0xc6,0xa5,0x56,0x90,0xc1,0x64}, |

142 | {0xc8,0xac,0x69,0xa1,0xe2,0x4e},{0xca,0xaf,0x60,0xaa,0xef,0x40}, |

143 | {0xcc,0xaa,0x7b,0xb7,0xf8,0x52},{0xce,0xa9,0x72,0xbc,0xf5,0x5c}, |

144 | {0xd0,0xb8,0x05,0xd5,0xbe,0x06},{0xd2,0xbb,0x0c,0xde,0xb3,0x08}, |

145 | {0xd4,0xbe,0x17,0xc3,0xa4,0x1a},{0xd6,0xbd,0x1e,0xc8,0xa9,0x14}, |

146 | {0xd8,0xb4,0x21,0xf9,0x8a,0x3e},{0xda,0xb7,0x28,0xf2,0x87,0x30}, |

147 | {0xdc,0xb2,0x33,0xef,0x90,0x22},{0xde,0xb1,0x3a,0xe4,0x9d,0x2c}, |

148 | {0xe0,0x90,0xdd,0x3d,0x06,0x96},{0xe2,0x93,0xd4,0x36,0x0b,0x98}, |

149 | {0xe4,0x96,0xcf,0x2b,0x1c,0x8a},{0xe6,0x95,0xc6,0x20,0x11,0x84}, |

150 | {0xe8,0x9c,0xf9,0x11,0x32,0xae},{0xea,0x9f,0xf0,0x1a,0x3f,0xa0}, |

151 | {0xec,0x9a,0xeb,0x07,0x28,0xb2},{0xee,0x99,0xe2,0x0c,0x25,0xbc}, |

152 | {0xf0,0x88,0x95,0x65,0x6e,0xe6},{0xf2,0x8b,0x9c,0x6e,0x63,0xe8}, |

153 | {0xf4,0x8e,0x87,0x73,0x74,0xfa},{0xf6,0x8d,0x8e,0x78,0x79,0xf4}, |

154 | {0xf8,0x84,0xb1,0x49,0x5a,0xde},{0xfa,0x87,0xb8,0x42,0x57,0xd0}, |

155 | {0xfc,0x82,0xa3,0x5f,0x40,0xc2},{0xfe,0x81,0xaa,0x54,0x4d,0xcc}, |

156 | {0x1b,0x9b,0xec,0xf7,0xda,0x41},{0x19,0x98,0xe5,0xfc,0xd7,0x4f}, |

157 | {0x1f,0x9d,0xfe,0xe1,0xc0,0x5d},{0x1d,0x9e,0xf7,0xea,0xcd,0x53}, |

158 | {0x13,0x97,0xc8,0xdb,0xee,0x79},{0x11,0x94,0xc1,0xd0,0xe3,0x77}, |

159 | {0x17,0x91,0xda,0xcd,0xf4,0x65},{0x15,0x92,0xd3,0xc6,0xf9,0x6b}, |

160 | {0x0b,0x83,0xa4,0xaf,0xb2,0x31},{0x09,0x80,0xad,0xa4,0xbf,0x3f}, |

161 | {0x0f,0x85,0xb6,0xb9,0xa8,0x2d},{0x0d,0x86,0xbf,0xb2,0xa5,0x23}, |

162 | {0x03,0x8f,0x80,0x83,0x86,0x09},{0x01,0x8c,0x89,0x88,0x8b,0x07}, |

163 | {0x07,0x89,0x92,0x95,0x9c,0x15},{0x05,0x8a,0x9b,0x9e,0x91,0x1b}, |

164 | {0x3b,0xab,0x7c,0x47,0x0a,0xa1},{0x39,0xa8,0x75,0x4c,0x07,0xaf}, |

165 | {0x3f,0xad,0x6e,0x51,0x10,0xbd},{0x3d,0xae,0x67,0x5a,0x1d,0xb3}, |

166 | {0x33,0xa7,0x58,0x6b,0x3e,0x99},{0x31,0xa4,0x51,0x60,0x33,0x97}, |

167 | {0x37,0xa1,0x4a,0x7d,0x24,0x85},{0x35,0xa2,0x43,0x76,0x29,0x8b}, |

168 | {0x2b,0xb3,0x34,0x1f,0x62,0xd1},{0x29,0xb0,0x3d,0x14,0x6f,0xdf}, |

169 | {0x2f,0xb5,0x26,0x09,0x78,0xcd},{0x2d,0xb6,0x2f,0x02,0x75,0xc3}, |

170 | {0x23,0xbf,0x10,0x33,0x56,0xe9},{0x21,0xbc,0x19,0x38,0x5b,0xe7}, |

171 | {0x27,0xb9,0x02,0x25,0x4c,0xf5},{0x25,0xba,0x0b,0x2e,0x41,0xfb}, |

172 | {0x5b,0xfb,0xd7,0x8c,0x61,0x9a},{0x59,0xf8,0xde,0x87,0x6c,0x94}, |

173 | {0x5f,0xfd,0xc5,0x9a,0x7b,0x86},{0x5d,0xfe,0xcc,0x91,0x76,0x88}, |

174 | {0x53,0xf7,0xf3,0xa0,0x55,0xa2},{0x51,0xf4,0xfa,0xab,0x58,0xac}, |

175 | {0x57,0xf1,0xe1,0xb6,0x4f,0xbe},{0x55,0xf2,0xe8,0xbd,0x42,0xb0}, |

176 | {0x4b,0xe3,0x9f,0xd4,0x09,0xea},{0x49,0xe0,0x96,0xdf,0x04,0xe4}, |

177 | {0x4f,0xe5,0x8d,0xc2,0x13,0xf6},{0x4d,0xe6,0x84,0xc9,0x1e,0xf8}, |

178 | {0x43,0xef,0xbb,0xf8,0x3d,0xd2},{0x41,0xec,0xb2,0xf3,0x30,0xdc}, |

179 | {0x47,0xe9,0xa9,0xee,0x27,0xce},{0x45,0xea,0xa0,0xe5,0x2a,0xc0}, |

180 | {0x7b,0xcb,0x47,0x3c,0xb1,0x7a},{0x79,0xc8,0x4e,0x37,0xbc,0x74}, |

181 | {0x7f,0xcd,0x55,0x2a,0xab,0x66},{0x7d,0xce,0x5c,0x21,0xa6,0x68}, |

182 | {0x73,0xc7,0x63,0x10,0x85,0x42},{0x71,0xc4,0x6a,0x1b,0x88,0x4c}, |

183 | {0x77,0xc1,0x71,0x06,0x9f,0x5e},{0x75,0xc2,0x78,0x0d,0x92,0x50}, |

184 | {0x6b,0xd3,0x0f,0x64,0xd9,0x0a},{0x69,0xd0,0x06,0x6f,0xd4,0x04}, |

185 | {0x6f,0xd5,0x1d,0x72,0xc3,0x16},{0x6d,0xd6,0x14,0x79,0xce,0x18}, |

186 | {0x63,0xdf,0x2b,0x48,0xed,0x32},{0x61,0xdc,0x22,0x43,0xe0,0x3c}, |

187 | {0x67,0xd9,0x39,0x5e,0xf7,0x2e},{0x65,0xda,0x30,0x55,0xfa,0x20}, |

188 | {0x9b,0x5b,0x9a,0x01,0xb7,0xec},{0x99,0x58,0x93,0x0a,0xba,0xe2}, |

189 | {0x9f,0x5d,0x88,0x17,0xad,0xf0},{0x9d,0x5e,0x81,0x1c,0xa0,0xfe}, |

190 | {0x93,0x57,0xbe,0x2d,0x83,0xd4},{0x91,0x54,0xb7,0x26,0x8e,0xda}, |

191 | {0x97,0x51,0xac,0x3b,0x99,0xc8},{0x95,0x52,0xa5,0x30,0x94,0xc6}, |

192 | {0x8b,0x43,0xd2,0x59,0xdf,0x9c},{0x89,0x40,0xdb,0x52,0xd2,0x92}, |

193 | {0x8f,0x45,0xc0,0x4f,0xc5,0x80},{0x8d,0x46,0xc9,0x44,0xc8,0x8e}, |

194 | {0x83,0x4f,0xf6,0x75,0xeb,0xa4},{0x81,0x4c,0xff,0x7e,0xe6,0xaa}, |

195 | {0x87,0x49,0xe4,0x63,0xf1,0xb8},{0x85,0x4a,0xed,0x68,0xfc,0xb6}, |

196 | {0xbb,0x6b,0x0a,0xb1,0x67,0x0c},{0xb9,0x68,0x03,0xba,0x6a,0x02}, |

197 | {0xbf,0x6d,0x18,0xa7,0x7d,0x10},{0xbd,0x6e,0x11,0xac,0x70,0x1e}, |

198 | {0xb3,0x67,0x2e,0x9d,0x53,0x34},{0xb1,0x64,0x27,0x96,0x5e,0x3a}, |

199 | {0xb7,0x61,0x3c,0x8b,0x49,0x28},{0xb5,0x62,0x35,0x80,0x44,0x26}, |

200 | {0xab,0x73,0x42,0xe9,0x0f,0x7c},{0xa9,0x70,0x4b,0xe2,0x02,0x72}, |

201 | {0xaf,0x75,0x50,0xff,0x15,0x60},{0xad,0x76,0x59,0xf4,0x18,0x6e}, |

202 | {0xa3,0x7f,0x66,0xc5,0x3b,0x44},{0xa1,0x7c,0x6f,0xce,0x36,0x4a}, |

203 | {0xa7,0x79,0x74,0xd3,0x21,0x58},{0xa5,0x7a,0x7d,0xd8,0x2c,0x56}, |

204 | {0xdb,0x3b,0xa1,0x7a,0x0c,0x37},{0xd9,0x38,0xa8,0x71,0x01,0x39}, |

205 | {0xdf,0x3d,0xb3,0x6c,0x16,0x2b},{0xdd,0x3e,0xba,0x67,0x1b,0x25}, |

206 | {0xd3,0x37,0x85,0x56,0x38,0x0f},{0xd1,0x34,0x8c,0x5d,0x35,0x01}, |

207 | {0xd7,0x31,0x97,0x40,0x22,0x13},{0xd5,0x32,0x9e,0x4b,0x2f,0x1d}, |

208 | {0xcb,0x23,0xe9,0x22,0x64,0x47},{0xc9,0x20,0xe0,0x29,0x69,0x49}, |

209 | {0xcf,0x25,0xfb,0x34,0x7e,0x5b},{0xcd,0x26,0xf2,0x3f,0x73,0x55}, |

210 | {0xc3,0x2f,0xcd,0x0e,0x50,0x7f},{0xc1,0x2c,0xc4,0x05,0x5d,0x71}, |

211 | {0xc7,0x29,0xdf,0x18,0x4a,0x63},{0xc5,0x2a,0xd6,0x13,0x47,0x6d}, |

212 | {0xfb,0x0b,0x31,0xca,0xdc,0xd7},{0xf9,0x08,0x38,0xc1,0xd1,0xd9}, |

213 | {0xff,0x0d,0x23,0xdc,0xc6,0xcb},{0xfd,0x0e,0x2a,0xd7,0xcb,0xc5}, |

214 | {0xf3,0x07,0x15,0xe6,0xe8,0xef},{0xf1,0x04,0x1c,0xed,0xe5,0xe1}, |

215 | {0xf7,0x01,0x07,0xf0,0xf2,0xf3},{0xf5,0x02,0x0e,0xfb,0xff,0xfd}, |

216 | {0xeb,0x13,0x79,0x92,0xb4,0xa7},{0xe9,0x10,0x70,0x99,0xb9,0xa9}, |

217 | {0xef,0x15,0x6b,0x84,0xae,0xbb},{0xed,0x16,0x62,0x8f,0xa3,0xb5}, |

218 | {0xe3,0x1f,0x5d,0xbe,0x80,0x9f},{0xe1,0x1c,0x54,0xb5,0x8d,0x91}, |

219 | {0xe7,0x19,0x4f,0xa8,0x9a,0x83},{0xe5,0x1a,0x46,0xa3,0x97,0x8d} |

220 | }; |

221 | |

222 | /*********************** FUNCTION DEFINITIONS ***********************/ |

223 | // XORs the in and out buffers, storing the result in out. Length is in bytes. |

224 | void xor_buf(const BYTE in[], BYTE out[], size_t len) |

225 | { |

226 | size_t idx; |

227 | |

228 | for (idx = 0; idx < len; idx++) |

229 | out[idx] ^= in[idx]; |

230 | } |

231 | |

232 | /******************* |

233 | * AES - CBC |

234 | *******************/ |

235 | int aes_encrypt_cbc(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) |

236 | { |

237 | BYTE buf_in[AES_BLOCK_SIZE], buf_out[AES_BLOCK_SIZE]; |

238 | int blocks, idx; |

239 | |

240 | if (in_len % AES_BLOCK_SIZE != 0) |

241 | return(FALSE); |

242 | |

243 | blocks = in_len / AES_BLOCK_SIZE; |

244 | |

245 | memcpy(dest: buf_out, src: iv, AES_BLOCK_SIZE); |

246 | |

247 | for (idx = 0; idx < blocks; idx++) { |

248 | memcpy(dest: buf_in, src: &in[idx * AES_BLOCK_SIZE], AES_BLOCK_SIZE); |

249 | xor_buf(in: buf_out, out: buf_in, AES_BLOCK_SIZE); |

250 | aes_encrypt(in: buf_in, out: buf_out, key, keysize); |

251 | memcpy(dest: &out[idx * AES_BLOCK_SIZE], src: 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]; |

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(dest: buf_out, src: iv, AES_BLOCK_SIZE); |

268 | |

269 | for (idx = 0; idx < blocks; idx++) { |

270 | memcpy(dest: buf_in, src: &in[idx * AES_BLOCK_SIZE], AES_BLOCK_SIZE); |

271 | xor_buf(in: buf_out, out: buf_in, AES_BLOCK_SIZE); |

272 | aes_encrypt(in: buf_in, out: buf_out, key, keysize); |

273 | // Do not output all encrypted blocks. |

274 | } |

275 | |

276 | memcpy(dest: out, src: buf_out, AES_BLOCK_SIZE); // Only output the last block. |

277 | |

278 | return(TRUE); |

279 | } |

280 | |

281 | // No need for an aes_decrypt_cbc() for just CCM. |

282 | |

283 | /******************* |

284 | * AES - CTR |

285 | *******************/ |

286 | void increment_iv(BYTE iv[], int counter_size) |

287 | { |

288 | int idx; |

289 | |

290 | // Use counter_size bytes at the end of the IV as the big-endian integer to increment. |

291 | for (idx = AES_BLOCK_SIZE - 1; idx >= AES_BLOCK_SIZE - counter_size; idx--) { |

292 | iv[idx]++; |

293 | if (iv[idx] != 0 || idx == AES_BLOCK_SIZE - counter_size) |

294 | break; |

295 | } |

296 | } |

297 | |

298 | // Performs the encryption in-place, the input and output buffers may be the same. |

299 | // Input may be an arbitrary length (in bytes). |

300 | void aes_encrypt_ctr(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) |

301 | { |

302 | size_t idx = 0, last_block_length; |

303 | BYTE iv_buf[AES_BLOCK_SIZE], out_buf[AES_BLOCK_SIZE]; |

304 | |

305 | if (in != out) |

306 | memcpy(dest: out, src: in, n: in_len); |

307 | |

308 | memcpy(dest: iv_buf, src: iv, AES_BLOCK_SIZE); |

309 | last_block_length = in_len - AES_BLOCK_SIZE; |

310 | |

311 | if (in_len > AES_BLOCK_SIZE) { |

312 | for (idx = 0; idx < last_block_length; idx += AES_BLOCK_SIZE) { |

313 | aes_encrypt(in: iv_buf, out: out_buf, key, keysize); |

314 | xor_buf(in: out_buf, out: &out[idx], AES_BLOCK_SIZE); |

315 | increment_iv(iv: iv_buf, AES_BLOCK_SIZE); |

316 | } |

317 | } |

318 | |

319 | aes_encrypt(in: iv_buf, out: out_buf, key, keysize); |

320 | xor_buf(in: out_buf, out: &out[idx], len: in_len - idx); // Use the Most Significant bytes. |

321 | } |

322 | |

323 | void aes_decrypt_ctr(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) |

324 | { |

325 | // CTR encryption is its own inverse function. |

326 | aes_encrypt_ctr(in, in_len, out, key, keysize, iv); |

327 | } |

328 | |

329 | /******************* |

330 | * AES - CCM |

331 | *******************/ |

332 | // out_len = payload_len + assoc_len |

333 | int aes_encrypt_ccm(const BYTE payload[], WORD payload_len, const BYTE assoc[], unsigned short assoc_len, |

334 | const BYTE nonce[], unsigned short nonce_len, BYTE out[], WORD *out_len, |

335 | WORD mac_len, const BYTE key_str[], int keysize) |

336 | { |

337 | BYTE temp_iv[AES_BLOCK_SIZE], counter[AES_BLOCK_SIZE], mac[16], *buf; |

338 | int end_of_buf, payload_len_store_size; |

339 | WORD key[60]; |

340 | |

341 | if (mac_len != 4 && mac_len != 6 && mac_len != 8 && mac_len != 10 && |

342 | mac_len != 12 && mac_len != 14 && mac_len != 16) |

343 | return(FALSE); |

344 | |

345 | if (nonce_len < 7 || nonce_len > 13) |

346 | return(FALSE); |

347 | |

348 | if (assoc_len > 32768 /* = 2^15 */) |

349 | return(FALSE); |

350 | |

351 | buf = (BYTE*)malloc(size: payload_len + assoc_len + 48 /*Round both payload and associated data up a block size and add an extra block.*/); |

352 | if (! buf) |

353 | return(FALSE); |

354 | |

355 | // Prepare the key for usage. |

356 | aes_key_setup(key: key_str, w: key, keysize); |

357 | |

358 | // Format the first block of the formatted data. |

359 | payload_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; |

360 | ccm_prepare_first_format_blk(buf, assoc_len, payload_len, payload_len_store_size, mac_len, nonce, nonce_len); |

361 | end_of_buf = AES_BLOCK_SIZE; |

362 | |

363 | // Format the Associated Data, aka, assoc[]. |

364 | ccm_format_assoc_data(buf, end_of_buf: &end_of_buf, assoc, assoc_len); |

365 | |

366 | // Format the Payload, aka payload[]. |

367 | ccm_format_payload_data(buf, end_of_buf: &end_of_buf, payload, payload_len); |

368 | |

369 | // Create the first counter block. |

370 | ccm_prepare_first_ctr_blk(counter, nonce, nonce_len, payload_len_store_size); |

371 | |

372 | // Perform the CBC operation with an IV of zeros on the formatted buffer to calculate the MAC. |

373 | memset(s: temp_iv, c: 0, AES_BLOCK_SIZE); |

374 | aes_encrypt_cbc_mac(in: buf, in_len: end_of_buf, out: mac, key, keysize, iv: temp_iv); |

375 | |

376 | // Copy the Payload and MAC to the output buffer. |

377 | memcpy(dest: out, src: payload, n: payload_len); |

378 | memcpy(dest: &out[payload_len], src: mac, n: mac_len); |

379 | |

380 | // Encrypt the Payload with CTR mode with a counter starting at 1. |

381 | memcpy(dest: temp_iv, src: counter, AES_BLOCK_SIZE); |

382 | increment_iv(iv: temp_iv, AES_BLOCK_SIZE - 1 - mac_len); // Last argument is the byte size of the counting portion of the counter block. /*BUG?*/ |

383 | aes_encrypt_ctr(in: out, in_len: payload_len, out, key, keysize, iv: temp_iv); |

384 | |

385 | // Encrypt the MAC with CTR mode with a counter starting at 0. |

386 | aes_encrypt_ctr(in: &out[payload_len], in_len: mac_len, out: &out[payload_len], key, keysize, iv: counter); |

387 | |

388 | free(ptr: buf); |

389 | *out_len = payload_len + mac_len; |

390 | |

391 | return(TRUE); |

392 | } |

393 | |

394 | // plaintext_len = ciphertext_len - mac_len |

395 | // Needs a flag for whether the MAC matches. |

396 | int aes_decrypt_ccm(const BYTE ciphertext[], WORD ciphertext_len, const BYTE assoc[], unsigned short assoc_len, |

397 | const BYTE nonce[], unsigned short nonce_len, BYTE plaintext[], WORD *plaintext_len, |

398 | WORD mac_len, int *mac_auth, const BYTE key_str[], int keysize) |

399 | { |

400 | BYTE temp_iv[AES_BLOCK_SIZE], counter[AES_BLOCK_SIZE], mac[16], mac_buf[16], *buf; |

401 | int end_of_buf, plaintext_len_store_size; |

402 | WORD key[60]; |

403 | |

404 | if (ciphertext_len <= mac_len) |

405 | return(FALSE); |

406 | |

407 | buf = (BYTE*)malloc(size: assoc_len + ciphertext_len /*ciphertext_len = plaintext_len + mac_len*/ + 48); |

408 | if (! buf) |

409 | return(FALSE); |

410 | |

411 | // Prepare the key for usage. |

412 | aes_key_setup(key: key_str, w: key, keysize); |

413 | |

414 | // Copy the plaintext and MAC to the output buffers. |

415 | *plaintext_len = ciphertext_len - mac_len; |

416 | plaintext_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; |

417 | memcpy(dest: plaintext, src: ciphertext, n: *plaintext_len); |

418 | memcpy(dest: mac, src: &ciphertext[*plaintext_len], n: mac_len); |

419 | |

420 | // Prepare the first counter block for use in decryption. |

421 | ccm_prepare_first_ctr_blk(counter, nonce, nonce_len, payload_len_store_size: plaintext_len_store_size); |

422 | |

423 | // Decrypt the Payload with CTR mode with a counter starting at 1. |

424 | memcpy(dest: temp_iv, src: counter, AES_BLOCK_SIZE); |

425 | increment_iv(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. |

426 | aes_decrypt_ctr(in: plaintext, in_len: *plaintext_len, out: plaintext, key, keysize, iv: temp_iv); |

427 | |

428 | // Setting mac_auth to NULL disables the authentication check. |

429 | if (mac_auth != NULL) { |

430 | // Decrypt the MAC with CTR mode with a counter starting at 0. |

431 | aes_decrypt_ctr(in: mac, in_len: mac_len, out: mac, key, keysize, iv: counter); |

432 | |

433 | // Format the first block of the formatted data. |

434 | plaintext_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; |

435 | ccm_prepare_first_format_blk(buf, assoc_len, payload_len: *plaintext_len, payload_len_store_size: plaintext_len_store_size, mac_len, nonce, nonce_len); |

436 | end_of_buf = AES_BLOCK_SIZE; |

437 | |

438 | // Format the Associated Data into the authentication buffer. |

439 | ccm_format_assoc_data(buf, end_of_buf: &end_of_buf, assoc, assoc_len); |

440 | |

441 | // Format the Payload into the authentication buffer. |

442 | ccm_format_payload_data(buf, end_of_buf: &end_of_buf, payload: plaintext, payload_len: *plaintext_len); |

443 | |

444 | // Perform the CBC operation with an IV of zeros on the formatted buffer to calculate the MAC. |

445 | memset(s: temp_iv, c: 0, AES_BLOCK_SIZE); |

446 | aes_encrypt_cbc_mac(in: buf, in_len: end_of_buf, out: mac_buf, key, keysize, iv: temp_iv); |

447 | |

448 | // Compare the calculated MAC against the MAC embedded in the ciphertext to see if they are the same. |

449 | if (! memcmp(s1: mac, s2: mac_buf, n: mac_len)) { |

450 | *mac_auth = TRUE; |

451 | } |

452 | else { |

453 | *mac_auth = FALSE; |

454 | memset(s: plaintext, c: 0, n: *plaintext_len); |

455 | } |

456 | } |

457 | |

458 | free(ptr: buf); |

459 | |

460 | return(TRUE); |

461 | } |

462 | |

463 | // Creates the first counter block. First byte is flags, then the nonce, then the incremented part. |

464 | void ccm_prepare_first_ctr_blk(BYTE counter[], const BYTE nonce[], int nonce_len, int payload_len_store_size) |

465 | { |

466 | memset(s: counter, c: 0, AES_BLOCK_SIZE); |

467 | counter[0] = (payload_len_store_size - 1) & 0x07; |

468 | memcpy(dest: &counter[1], src: nonce, n: nonce_len); |

469 | } |

470 | |

471 | 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) |

472 | { |

473 | // Set the flags for the first byte of the first block. |

474 | buf[0] = ((((mac_len - 2) / 2) & 0x07) << 3) | ((payload_len_store_size - 1) & 0x07); |

475 | if (assoc_len > 0) |

476 | buf[0] += 0x40; |

477 | // Format the rest of the first block, storing the nonce and the size of the payload. |

478 | memcpy(dest: &buf[1], src: nonce, n: nonce_len); |

479 | memset(s: &buf[1 + nonce_len], c: 0, AES_BLOCK_SIZE - 1 - nonce_len); |

480 | buf[15] = payload_len & 0x000000FF; |

481 | buf[14] = (payload_len >> 8) & 0x000000FF; |

482 | } |

483 | |

484 | void ccm_format_assoc_data(BYTE buf[], int *end_of_buf, const BYTE assoc[], int assoc_len) |

485 | { |

486 | int pad; |

487 | |

488 | buf[*end_of_buf + 1] = assoc_len & 0x00FF; |

489 | buf[*end_of_buf] = (assoc_len >> 8) & 0x00FF; |

490 | *end_of_buf += 2; |

491 | memcpy(dest: &buf[*end_of_buf], src: assoc, n: assoc_len); |

492 | *end_of_buf += assoc_len; |

493 | pad = AES_BLOCK_SIZE - (*end_of_buf % AES_BLOCK_SIZE); /*BUG?*/ |

494 | memset(s: &buf[*end_of_buf], c: 0, n: pad); |

495 | *end_of_buf += pad; |

496 | } |

497 | |

498 | void ccm_format_payload_data(BYTE buf[], int *end_of_buf, const BYTE payload[], int payload_len) |

499 | { |

500 | int pad; |

501 | |

502 | memcpy(dest: &buf[*end_of_buf], src: payload, n: payload_len); |

503 | *end_of_buf += payload_len; |

504 | pad = *end_of_buf % AES_BLOCK_SIZE; |

505 | if (pad != 0) |

506 | pad = AES_BLOCK_SIZE - pad; |

507 | memset(s: &buf[*end_of_buf], c: 0, n: pad); |

508 | *end_of_buf += pad; |

509 | } |

510 | |

511 | /******************* |

512 | * AES |

513 | *******************/ |

514 | ///////////////// |

515 | // KEY EXPANSION |

516 | ///////////////// |

517 | |

518 | // Substitutes a word using the AES S-Box. |

519 | WORD SubWord(WORD word) |

520 | { |

521 | unsigned int result; |

522 | |

523 | result = (int)aes_sbox[(word >> 4) & 0x0000000F][word & 0x0000000F]; |

524 | result += (int)aes_sbox[(word >> 12) & 0x0000000F][(word >> 8) & 0x0000000F] << 8; |

525 | result += (int)aes_sbox[(word >> 20) & 0x0000000F][(word >> 16) & 0x0000000F] << 16; |

526 | result += (int)aes_sbox[(word >> 28) & 0x0000000F][(word >> 24) & 0x0000000F] << 24; |

527 | return(result); |

528 | } |

529 | |

530 | // Performs the action of generating the keys that will be used in every round of |

531 | // encryption. "key" is the user-supplied input key, "w" is the output key schedule, |

532 | // "keysize" is the length in bits of "key", must be 128, 192, or 256. |

533 | void aes_key_setup(const BYTE key[], WORD w[], int keysize) |

534 | { |

535 | int Nb=4,Nr,Nk,idx; |

536 | WORD temp,Rcon[]={0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000, |

537 | 0x40000000,0x80000000,0x1b000000,0x36000000,0x6c000000,0xd8000000, |

538 | 0xab000000,0x4d000000,0x9a000000}; |

539 | |

540 | switch (keysize) { |

541 | case 128: Nr = 10; Nk = 4; break; |

542 | case 192: Nr = 12; Nk = 6; break; |

543 | case 256: Nr = 14; Nk = 8; break; |

544 | default: return; |

545 | } |

546 | |

547 | for (idx=0; idx < Nk; ++idx) { |

548 | w[idx] = ((key[4 * idx]) << 24) | ((key[4 * idx + 1]) << 16) | |

549 | ((key[4 * idx + 2]) << 8) | ((key[4 * idx + 3])); |

550 | } |

551 | |

552 | for (idx = Nk; idx < Nb * (Nr+1); ++idx) { |

553 | temp = w[idx - 1]; |

554 | if ((idx % Nk) == 0) |

555 | temp = SubWord(KE_ROTWORD(temp)) ^ Rcon[(idx-1)/Nk]; |

556 | else if (Nk > 6 && (idx % Nk) == 4) |

557 | temp = SubWord(word: temp); |

558 | w[idx] = w[idx-Nk] ^ temp; |

559 | } |

560 | } |

561 | |

562 | ///////////////// |

563 | // ADD ROUND KEY |

564 | ///////////////// |

565 | |

566 | // Performs the AddRoundKey step. Each round has its own pre-generated 16-byte key in the |

567 | // form of 4 integers (the "w" array). Each integer is XOR'd by one column of the state. |

568 | // Also performs the job of InvAddRoundKey(); since the function is a simple XOR process, |

569 | // it is its own inverse. |

570 | void AddRoundKey(BYTE state[][4], const WORD w[]) |

571 | { |

572 | BYTE subkey[4]; |

573 | |

574 | // memcpy(subkey,&w[idx],4); // Not accurate for big endian machines |

575 | // Subkey 1 |

576 | subkey[0] = w[0] >> 24; |

577 | subkey[1] = w[0] >> 16; |

578 | subkey[2] = w[0] >> 8; |

579 | subkey[3] = w[0]; |

580 | state[0][0] ^= subkey[0]; |

581 | state[1][0] ^= subkey[1]; |

582 | state[2][0] ^= subkey[2]; |

583 | state[3][0] ^= subkey[3]; |

584 | // Subkey 2 |

585 | subkey[0] = w[1] >> 24; |

586 | subkey[1] = w[1] >> 16; |

587 | subkey[2] = w[1] >> 8; |

588 | subkey[3] = w[1]; |

589 | state[0][1] ^= subkey[0]; |

590 | state[1][1] ^= subkey[1]; |

591 | state[2][1] ^= subkey[2]; |

592 | state[3][1] ^= subkey[3]; |

593 | // Subkey 3 |

594 | subkey[0] = w[2] >> 24; |

595 | subkey[1] = w[2] >> 16; |

596 | subkey[2] = w[2] >> 8; |

597 | subkey[3] = w[2]; |

598 | state[0][2] ^= subkey[0]; |

599 | state[1][2] ^= subkey[1]; |

600 | state[2][2] ^= subkey[2]; |

601 | state[3][2] ^= subkey[3]; |

602 | // Subkey 4 |

603 | subkey[0] = w[3] >> 24; |

604 | subkey[1] = w[3] >> 16; |

605 | subkey[2] = w[3] >> 8; |

606 | subkey[3] = w[3]; |

607 | state[0][3] ^= subkey[0]; |

608 | state[1][3] ^= subkey[1]; |

609 | state[2][3] ^= subkey[2]; |

610 | state[3][3] ^= subkey[3]; |

611 | } |

612 | |

613 | ///////////////// |

614 | // (Inv)SubBytes |

615 | ///////////////// |

616 | |

617 | // Performs the SubBytes step. All bytes in the state are substituted with a |

618 | // pre-calculated value from a lookup table. |

619 | void SubBytes(BYTE state[][4]) |

620 | { |

621 | state[0][0] = aes_sbox[state[0][0] >> 4][state[0][0] & 0x0F]; |

622 | state[0][1] = aes_sbox[state[0][1] >> 4][state[0][1] & 0x0F]; |

623 | state[0][2] = aes_sbox[state[0][2] >> 4][state[0][2] & 0x0F]; |

624 | state[0][3] = aes_sbox[state[0][3] >> 4][state[0][3] & 0x0F]; |

625 | state[1][0] = aes_sbox[state[1][0] >> 4][state[1][0] & 0x0F]; |

626 | state[1][1] = aes_sbox[state[1][1] >> 4][state[1][1] & 0x0F]; |

627 | state[1][2] = aes_sbox[state[1][2] >> 4][state[1][2] & 0x0F]; |

628 | state[1][3] = aes_sbox[state[1][3] >> 4][state[1][3] & 0x0F]; |

629 | state[2][0] = aes_sbox[state[2][0] >> 4][state[2][0] & 0x0F]; |

630 | state[2][1] = aes_sbox[state[2][1] >> 4][state[2][1] & 0x0F]; |

631 | state[2][2] = aes_sbox[state[2][2] >> 4][state[2][2] & 0x0F]; |

632 | state[2][3] = aes_sbox[state[2][3] >> 4][state[2][3] & 0x0F]; |

633 | state[3][0] = aes_sbox[state[3][0] >> 4][state[3][0] & 0x0F]; |

634 | state[3][1] = aes_sbox[state[3][1] >> 4][state[3][1] & 0x0F]; |

635 | state[3][2] = aes_sbox[state[3][2] >> 4][state[3][2] & 0x0F]; |

636 | state[3][3] = aes_sbox[state[3][3] >> 4][state[3][3] & 0x0F]; |

637 | } |

638 | |

639 | void InvSubBytes(BYTE state[][4]) |

640 | { |

641 | state[0][0] = aes_invsbox[state[0][0] >> 4][state[0][0] & 0x0F]; |

642 | state[0][1] = aes_invsbox[state[0][1] >> 4][state[0][1] & 0x0F]; |

643 | state[0][2] = aes_invsbox[state[0][2] >> 4][state[0][2] & 0x0F]; |

644 | state[0][3] = aes_invsbox[state[0][3] >> 4][state[0][3] & 0x0F]; |

645 | state[1][0] = aes_invsbox[state[1][0] >> 4][state[1][0] & 0x0F]; |

646 | state[1][1] = aes_invsbox[state[1][1] >> 4][state[1][1] & 0x0F]; |

647 | state[1][2] = aes_invsbox[state[1][2] >> 4][state[1][2] & 0x0F]; |

648 | state[1][3] = aes_invsbox[state[1][3] >> 4][state[1][3] & 0x0F]; |

649 | state[2][0] = aes_invsbox[state[2][0] >> 4][state[2][0] & 0x0F]; |

650 | state[2][1] = aes_invsbox[state[2][1] >> 4][state[2][1] & 0x0F]; |

651 | state[2][2] = aes_invsbox[state[2][2] >> 4][state[2][2] & 0x0F]; |

652 | state[2][3] = aes_invsbox[state[2][3] >> 4][state[2][3] & 0x0F]; |

653 | state[3][0] = aes_invsbox[state[3][0] >> 4][state[3][0] & 0x0F]; |

654 | state[3][1] = aes_invsbox[state[3][1] >> 4][state[3][1] & 0x0F]; |

655 | state[3][2] = aes_invsbox[state[3][2] >> 4][state[3][2] & 0x0F]; |

656 | state[3][3] = aes_invsbox[state[3][3] >> 4][state[3][3] & 0x0F]; |

657 | } |

658 | |

659 | ///////////////// |

660 | // (Inv)ShiftRows |

661 | ///////////////// |

662 | |

663 | // Performs the ShiftRows step. All rows are shifted cylindrically to the left. |

664 | void ShiftRows(BYTE state[][4]) |

665 | { |

666 | int t; |

667 | |

668 | // Shift left by 1 |

669 | t = state[1][0]; |

670 | state[1][0] = state[1][1]; |

671 | state[1][1] = state[1][2]; |

672 | state[1][2] = state[1][3]; |

673 | state[1][3] = t; |

674 | // Shift left by 2 |

675 | t = state[2][0]; |

676 | state[2][0] = state[2][2]; |

677 | state[2][2] = t; |

678 | t = state[2][1]; |

679 | state[2][1] = state[2][3]; |

680 | state[2][3] = t; |

681 | // Shift left by 3 |

682 | t = state[3][0]; |

683 | state[3][0] = state[3][3]; |

684 | state[3][3] = state[3][2]; |

685 | state[3][2] = state[3][1]; |

686 | state[3][1] = t; |

687 | } |

688 | |

689 | // All rows are shifted cylindrically to the right. |

690 | void InvShiftRows(BYTE state[][4]) |

691 | { |

692 | int t; |

693 | |

694 | // Shift right by 1 |

695 | t = state[1][3]; |

696 | state[1][3] = state[1][2]; |

697 | state[1][2] = state[1][1]; |

698 | state[1][1] = state[1][0]; |

699 | state[1][0] = t; |

700 | // Shift right by 2 |

701 | t = state[2][3]; |

702 | state[2][3] = state[2][1]; |

703 | state[2][1] = t; |

704 | t = state[2][2]; |

705 | state[2][2] = state[2][0]; |

706 | state[2][0] = t; |

707 | // Shift right by 3 |

708 | t = state[3][3]; |

709 | state[3][3] = state[3][0]; |

710 | state[3][0] = state[3][1]; |

711 | state[3][1] = state[3][2]; |

712 | state[3][2] = t; |

713 | } |

714 | |

715 | ///////////////// |

716 | // (Inv)MixColumns |

717 | ///////////////// |

718 | |

719 | // Performs the MixColums step. The state is multiplied by itself using matrix |

720 | // multiplication in a Galios Field 2^8. All multiplication is pre-computed in a table. |

721 | // Addition is equivilent to XOR. (Must always make a copy of the column as the original |

722 | // values will be destoyed.) |

723 | void MixColumns(BYTE state[][4]) |

724 | { |

725 | BYTE col[4]; |

726 | |

727 | // Column 1 |

728 | col[0] = state[0][0]; |

729 | col[1] = state[1][0]; |

730 | col[2] = state[2][0]; |

731 | col[3] = state[3][0]; |

732 | state[0][0] = gf_mul[col[0]][0]; |

733 | state[0][0] ^= gf_mul[col[1]][1]; |

734 | state[0][0] ^= col[2]; |

735 | state[0][0] ^= col[3]; |

736 | state[1][0] = col[0]; |

737 | state[1][0] ^= gf_mul[col[1]][0]; |

738 | state[1][0] ^= gf_mul[col[2]][1]; |

739 | state[1][0] ^= col[3]; |

740 | state[2][0] = col[0]; |

741 | state[2][0] ^= col[1]; |

742 | state[2][0] ^= gf_mul[col[2]][0]; |

743 | state[2][0] ^= gf_mul[col[3]][1]; |

744 | state[3][0] = gf_mul[col[0]][1]; |

745 | state[3][0] ^= col[1]; |

746 | state[3][0] ^= col[2]; |

747 | state[3][0] ^= gf_mul[col[3]][0]; |

748 | // Column 2 |

749 | col[0] = state[0][1]; |

750 | col[1] = state[1][1]; |

751 | col[2] = state[2][1]; |

752 | col[3] = state[3][1]; |

753 | state[0][1] = gf_mul[col[0]][0]; |

754 | state[0][1] ^= gf_mul[col[1]][1]; |

755 | state[0][1] ^= col[2]; |

756 | state[0][1] ^= col[3]; |

757 | state[1][1] = col[0]; |

758 | state[1][1] ^= gf_mul[col[1]][0]; |

759 | state[1][1] ^= gf_mul[col[2]][1]; |

760 | state[1][1] ^= col[3]; |

761 | state[2][1] = col[0]; |

762 | state[2][1] ^= col[1]; |

763 | state[2][1] ^= gf_mul[col[2]][0]; |

764 | state[2][1] ^= gf_mul[col[3]][1]; |

765 | state[3][1] = gf_mul[col[0]][1]; |

766 | state[3][1] ^= col[1]; |

767 | state[3][1] ^= col[2]; |

768 | state[3][1] ^= gf_mul[col[3]][0]; |

769 | // Column 3 |

770 | col[0] = state[0][2]; |

771 | col[1] = state[1][2]; |

772 | col[2] = state[2][2]; |

773 | col[3] = state[3][2]; |

774 | state[0][2] = gf_mul[col[0]][0]; |

775 | state[0][2] ^= gf_mul[col[1]][1]; |

776 | state[0][2] ^= col[2]; |

777 | state[0][2] ^= col[3]; |

778 | state[1][2] = col[0]; |

779 | state[1][2] ^= gf_mul[col[1]][0]; |

780 | state[1][2] ^= gf_mul[col[2]][1]; |

781 | state[1][2] ^= col[3]; |

782 | state[2][2] = col[0]; |

783 | state[2][2] ^= col[1]; |

784 | state[2][2] ^= gf_mul[col[2]][0]; |

785 | state[2][2] ^= gf_mul[col[3]][1]; |

786 | state[3][2] = gf_mul[col[0]][1]; |

787 | state[3][2] ^= col[1]; |

788 | state[3][2] ^= col[2]; |

789 | state[3][2] ^= gf_mul[col[3]][0]; |

790 | // Column 4 |

791 | col[0] = state[0][3]; |

792 | col[1] = state[1][3]; |

793 | col[2] = state[2][3]; |

794 | col[3] = state[3][3]; |

795 | state[0][3] = gf_mul[col[0]][0]; |

796 | state[0][3] ^= gf_mul[col[1]][1]; |

797 | state[0][3] ^= col[2]; |

798 | state[0][3] ^= col[3]; |

799 | state[1][3] = col[0]; |

800 | state[1][3] ^= gf_mul[col[1]][0]; |

801 | state[1][3] ^= gf_mul[col[2]][1]; |

802 | state[1][3] ^= col[3]; |

803 | state[2][3] = col[0]; |

804 | state[2][3] ^= col[1]; |

805 | state[2][3] ^= gf_mul[col[2]][0]; |

806 | state[2][3] ^= gf_mul[col[3]][1]; |

807 | state[3][3] = gf_mul[col[0]][1]; |

808 | state[3][3] ^= col[1]; |

809 | state[3][3] ^= col[2]; |

810 | state[3][3] ^= gf_mul[col[3]][0]; |

811 | } |

812 | |

813 | void InvMixColumns(BYTE state[][4]) |

814 | { |

815 | BYTE col[4]; |

816 | |

817 | // Column 1 |

818 | col[0] = state[0][0]; |

819 | col[1] = state[1][0]; |

820 | col[2] = state[2][0]; |

821 | col[3] = state[3][0]; |

822 | state[0][0] = gf_mul[col[0]][5]; |

823 | state[0][0] ^= gf_mul[col[1]][3]; |

824 | state[0][0] ^= gf_mul[col[2]][4]; |

825 | state[0][0] ^= gf_mul[col[3]][2]; |

826 | state[1][0] = gf_mul[col[0]][2]; |

827 | state[1][0] ^= gf_mul[col[1]][5]; |

828 | state[1][0] ^= gf_mul[col[2]][3]; |

829 | state[1][0] ^= gf_mul[col[3]][4]; |

830 | state[2][0] = gf_mul[col[0]][4]; |

831 | state[2][0] ^= gf_mul[col[1]][2]; |

832 | state[2][0] ^= gf_mul[col[2]][5]; |

833 | state[2][0] ^= gf_mul[col[3]][3]; |

834 | state[3][0] = gf_mul[col[0]][3]; |

835 | state[3][0] ^= gf_mul[col[1]][4]; |

836 | state[3][0] ^= gf_mul[col[2]][2]; |

837 | state[3][0] ^= gf_mul[col[3]][5]; |

838 | // Column 2 |

839 | col[0] = state[0][1]; |

840 | col[1] = state[1][1]; |

841 | col[2] = state[2][1]; |

842 | col[3] = state[3][1]; |

843 | state[0][1] = gf_mul[col[0]][5]; |

844 | state[0][1] ^= gf_mul[col[1]][3]; |

845 | state[0][1] ^= gf_mul[col[2]][4]; |

846 | state[0][1] ^= gf_mul[col[3]][2]; |

847 | state[1][1] = gf_mul[col[0]][2]; |

848 | state[1][1] ^= gf_mul[col[1]][5]; |

849 | state[1][1] ^= gf_mul[col[2]][3]; |

850 | state[1][1] ^= gf_mul[col[3]][4]; |

851 | state[2][1] = gf_mul[col[0]][4]; |

852 | state[2][1] ^= gf_mul[col[1]][2]; |

853 | state[2][1] ^= gf_mul[col[2]][5]; |

854 | state[2][1] ^= gf_mul[col[3]][3]; |

855 | state[3][1] = gf_mul[col[0]][3]; |

856 | state[3][1] ^= gf_mul[col[1]][4]; |

857 | state[3][1] ^= gf_mul[col[2]][2]; |

858 | state[3][1] ^= gf_mul[col[3]][5]; |

859 | // Column 3 |

860 | col[0] = state[0][2]; |

861 | col[1] = state[1][2]; |

862 | col[2] = state[2][2]; |

863 | col[3] = state[3][2]; |

864 | state[0][2] = gf_mul[col[0]][5]; |

865 | state[0][2] ^= gf_mul[col[1]][3]; |

866 | state[0][2] ^= gf_mul[col[2]][4]; |

867 | state[0][2] ^= gf_mul[col[3]][2]; |

868 | state[1][2] = gf_mul[col[0]][2]; |

869 | state[1][2] ^= gf_mul[col[1]][5]; |

870 | state[1][2] ^= gf_mul[col[2]][3]; |

871 | state[1][2] ^= gf_mul[col[3]][4]; |

872 | state[2][2] = gf_mul[col[0]][4]; |

873 | state[2][2] ^= gf_mul[col[1]][2]; |

874 | state[2][2] ^= gf_mul[col[2]][5]; |

875 | state[2][2] ^= gf_mul[col[3]][3]; |

876 | state[3][2] = gf_mul[col[0]][3]; |

877 | state[3][2] ^= gf_mul[col[1]][4]; |

878 | state[3][2] ^= gf_mul[col[2]][2]; |

879 | state[3][2] ^= gf_mul[col[3]][5]; |

880 | // Column 4 |

881 | col[0] = state[0][3]; |

882 | col[1] = state[1][3]; |

883 | col[2] = state[2][3]; |

884 | col[3] = state[3][3]; |

885 | state[0][3] = gf_mul[col[0]][5]; |

886 | state[0][3] ^= gf_mul[col[1]][3]; |

887 | state[0][3] ^= gf_mul[col[2]][4]; |

888 | state[0][3] ^= gf_mul[col[3]][2]; |

889 | state[1][3] = gf_mul[col[0]][2]; |

890 | state[1][3] ^= gf_mul[col[1]][5]; |

891 | state[1][3] ^= gf_mul[col[2]][3]; |

892 | state[1][3] ^= gf_mul[col[3]][4]; |

893 | state[2][3] = gf_mul[col[0]][4]; |

894 | state[2][3] ^= gf_mul[col[1]][2]; |

895 | state[2][3] ^= gf_mul[col[2]][5]; |

896 | state[2][3] ^= gf_mul[col[3]][3]; |

897 | state[3][3] = gf_mul[col[0]][3]; |

898 | state[3][3] ^= gf_mul[col[1]][4]; |

899 | state[3][3] ^= gf_mul[col[2]][2]; |

900 | state[3][3] ^= gf_mul[col[3]][5]; |

901 | } |

902 | |

903 | ///////////////// |

904 | // (En/De)Crypt |

905 | ///////////////// |

906 | |

907 | void aes_encrypt(const BYTE in[], BYTE out[], const WORD key[], int keysize) |

908 | { |

909 | BYTE state[4][4]; |

910 | |

911 | // Copy input array (should be 16 bytes long) to a matrix (sequential bytes are ordered |

912 | // by row, not col) called "state" for processing. |

913 | // *** Implementation note: The official AES documentation references the state by |

914 | // column, then row. Accessing an element in C requires row then column. Thus, all state |

915 | // references in AES must have the column and row indexes reversed for C implementation. |

916 | state[0][0] = in[0]; |

917 | state[1][0] = in[1]; |

918 | state[2][0] = in[2]; |

919 | state[3][0] = in[3]; |

920 | state[0][1] = in[4]; |

921 | state[1][1] = in[5]; |

922 | state[2][1] = in[6]; |

923 | state[3][1] = in[7]; |

924 | state[0][2] = in[8]; |

925 | state[1][2] = in[9]; |

926 | state[2][2] = in[10]; |

927 | state[3][2] = in[11]; |

928 | state[0][3] = in[12]; |

929 | state[1][3] = in[13]; |

930 | state[2][3] = in[14]; |

931 | state[3][3] = in[15]; |

932 | |

933 | // Perform the necessary number of rounds. The round key is added first. |

934 | // The last round does not perform the MixColumns step. |

935 | AddRoundKey(state,w: &key[0]); |

936 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[4]); |

937 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[8]); |

938 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[12]); |

939 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[16]); |

940 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[20]); |

941 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[24]); |

942 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[28]); |

943 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[32]); |

944 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[36]); |

945 | if (keysize != 128) { |

946 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[40]); |

947 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[44]); |

948 | if (keysize != 192) { |

949 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[48]); |

950 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,w: &key[52]); |

951 | SubBytes(state); ShiftRows(state); AddRoundKey(state,w: &key[56]); |

952 | } |

953 | else { |

954 | SubBytes(state); ShiftRows(state); AddRoundKey(state,w: &key[48]); |

955 | } |

956 | } |

957 | else { |

958 | SubBytes(state); ShiftRows(state); AddRoundKey(state,w: &key[40]); |

959 | } |

960 | |

961 | // Copy the state to the output array. |

962 | out[0] = state[0][0]; |

963 | out[1] = state[1][0]; |

964 | out[2] = state[2][0]; |

965 | out[3] = state[3][0]; |

966 | out[4] = state[0][1]; |

967 | out[5] = state[1][1]; |

968 | out[6] = state[2][1]; |

969 | out[7] = state[3][1]; |

970 | out[8] = state[0][2]; |

971 | out[9] = state[1][2]; |

972 | out[10] = state[2][2]; |

973 | out[11] = state[3][2]; |

974 | out[12] = state[0][3]; |

975 | out[13] = state[1][3]; |

976 | out[14] = state[2][3]; |

977 | out[15] = state[3][3]; |

978 | } |

979 | |

980 | void aes_decrypt(const BYTE in[], BYTE out[], const WORD key[], int keysize) |

981 | { |

982 | BYTE state[4][4]; |

983 | |

984 | // Copy the input to the state. |

985 | state[0][0] = in[0]; |

986 | state[1][0] = in[1]; |

987 | state[2][0] = in[2]; |

988 | state[3][0] = in[3]; |

989 | state[0][1] = in[4]; |

990 | state[1][1] = in[5]; |

991 | state[2][1] = in[6]; |

992 | state[3][1] = in[7]; |

993 | state[0][2] = in[8]; |

994 | state[1][2] = in[9]; |

995 | state[2][2] = in[10]; |

996 | state[3][2] = in[11]; |

997 | state[0][3] = in[12]; |

998 | state[1][3] = in[13]; |

999 | state[2][3] = in[14]; |

1000 | state[3][3] = in[15]; |

1001 | |

1002 | // Perform the necessary number of rounds. The round key is added first. |

1003 | // The last round does not perform the MixColumns step. |

1004 | if (keysize > 128) { |

1005 | if (keysize > 192) { |

1006 | AddRoundKey(state,w: &key[56]); |

1007 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[52]);InvMixColumns(state); |

1008 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[48]);InvMixColumns(state); |

1009 | } |

1010 | else { |

1011 | AddRoundKey(state,w: &key[48]); |

1012 | } |

1013 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[44]);InvMixColumns(state); |

1014 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[40]);InvMixColumns(state); |

1015 | } |

1016 | else { |

1017 | AddRoundKey(state,w: &key[40]); |

1018 | } |

1019 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[36]);InvMixColumns(state); |

1020 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[32]);InvMixColumns(state); |

1021 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[28]);InvMixColumns(state); |

1022 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[24]);InvMixColumns(state); |

1023 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[20]);InvMixColumns(state); |

1024 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[16]);InvMixColumns(state); |

1025 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[12]);InvMixColumns(state); |

1026 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[8]);InvMixColumns(state); |

1027 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[4]);InvMixColumns(state); |

1028 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,w: &key[0]); |

1029 | |

1030 | // Copy the state to the output array. |

1031 | out[0] = state[0][0]; |

1032 | out[1] = state[1][0]; |

1033 | out[2] = state[2][0]; |

1034 | out[3] = state[3][0]; |

1035 | out[4] = state[0][1]; |

1036 | out[5] = state[1][1]; |

1037 | out[6] = state[2][1]; |

1038 | out[7] = state[3][1]; |

1039 | out[8] = state[0][2]; |

1040 | out[9] = state[1][2]; |

1041 | out[10] = state[2][2]; |

1042 | out[11] = state[3][2]; |

1043 | out[12] = state[0][3]; |

1044 | out[13] = state[1][3]; |

1045 | out[14] = state[2][3]; |

1046 | out[15] = state[3][3]; |

1047 | } |

1048 | |

1049 | /******************* |

1050 | ** AES DEBUGGING FUNCTIONS |

1051 | *******************/ |

1052 | /* |

1053 | // This prints the "state" grid as a linear hex string. |

1054 | void print_state(BYTE state[][4]) |

1055 | { |

1056 | int idx,idx2; |

1057 | |

1058 | for (idx=0; idx < 4; idx++) |

1059 | for (idx2=0; idx2 < 4; idx2++) |

1060 | printf("%02x",state[idx2][idx]); |

1061 | printf("\n"); |

1062 | } |

1063 | |

1064 | // This prints the key (4 consecutive ints) used for a given round as a linear hex string. |

1065 | void print_rnd_key(WORD key[]) |

1066 | { |

1067 | int idx; |

1068 | |

1069 | for (idx=0; idx < 4; idx++) |

1070 | printf("%08x",key[idx]); |

1071 | printf("\n"); |

1072 | } |

1073 | */ |

1074 |