注:java 为no-padding 注释掉了 padding部分(byte数组初始化时 为0x00)
c 为 padding 0x00 (byte数组初始化时 为0x00)
代码出自网上

代码地址 github
https://github.com/mountwater/AES-128-ECB-java_and_c JAVA代码

//Copyright Popa Tiberiu 2011 

//free to use this in any way 


package tsd.crypto.algoritm; 


public class AES { 


 private static int Nb, Nk, Nr; 

 private static byte[][] w; 


 private static int[] sbox = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 

 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 

 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 

 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 

 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 

 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 

 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 

 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 

 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 

 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 

 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 

 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 

 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 

 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 

 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 

 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 

 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 

 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 

 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 

 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 

 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 

 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 

 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 

 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; 


 private static int[] inv_sbox = { 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 

 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 

 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 

 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 

 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 

 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 

 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 

 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 

 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 

 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 

 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 

 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 

 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 

 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 

 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 

 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 

 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 

 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 

 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 

 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 

 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 

 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 

 0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 

 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; 


 private static int Rcon[] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 

 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 

 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 

 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 

 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 

 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 

 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 

 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 

 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 

 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 

 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 

 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 

 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 

 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 

 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 

 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb }; 


 private static byte[] xor_func(byte[] a, byte[] b) { 

 byte[] out = new byte[a.length]; 

 for (int i = 0; i < a.length; i++) { 

 out[i] = (byte) (a[i] ^ b[i]); 

 } 

 return out; 


 } 


 private static byte[][] generateSubkeys(byte[] key) { 

 byte[][] tmp = new byte[Nb * (Nr + 1)][4]; 


 int i = 0; 

 while (i < Nk) { 


 tmp[i][0] = key[i * 4]; 

 tmp[i][1] = key[i * 4 + 1]; 

 tmp[i][2] = key[i * 4 + 2]; 

 tmp[i][3] = key[i * 4 + 3]; 

 i++; 

 } 

 i = Nk; 

 while (i < Nb * (Nr + 1)) { 

 byte[] temp = new byte[4]; 

 for(int k = 0;k<4;k++) 

 temp[k] = tmp[i-1][k]; 

 if (i % Nk == 0) { 

 temp = SubWord(rotateWord(temp)); 

 temp[0] = (byte) (temp[0] ^ (Rcon[i / Nk] & 0xff)); 

 } else if (Nk > 6 && i % Nk == 4) { 

 temp = SubWord(temp); 

 } 

 tmp[i] = xor_func(tmp[i - Nk], temp); 

 i++; 

 } 


 return tmp; 

 } 


 private static byte[] SubWord(byte[] in) { 

 byte[] tmp = new byte[in.length]; 


 for (int i = 0; i < tmp.length; i++) 

 tmp[i] = (byte) (sbox[in[i] & 0x000000ff] & 0xff); 


 return tmp; 

 } 


 private static byte[] rotateWord(byte[] input) { 

 byte[] tmp = new byte[input.length]; 

 tmp[0] = input[1]; 

 tmp[1] = input[2]; 

 tmp[2] = input[3]; 

 tmp[3] = input[0]; 


 return tmp; 

 } 


 private static byte[][] AddRoundKey(byte[][] state, byte[][] w, int round) { 


 byte[][] tmp = new byte[state.length][state[0].length]; 


 for (int c = 0; c < Nb; c++) { 

 for (int l = 0; l < 4; l++) 

 tmp[l][c] = (byte) (state[l][c] ^ w[round * Nb + c][l]); 

 } 


 return tmp; 

 } 


 private static byte[][] SubBytes(byte[][] state) { 


 byte[][] tmp = new byte[state.length][state[0].length]; 

 for (int row = 0; row < 4; row++) 

 for (int col = 0; col < Nb; col++) 

 tmp[row][col] = (byte) (sbox[(state[row][col] & 0x000000ff)] & 0xff); 


 return tmp; 

 } 

 private static byte[][] InvSubBytes(byte[][] state) { 

 for (int row = 0; row < 4; row++) 

 for (int col = 0; col < Nb; col++) 

 state[row][col] = (byte)(inv_sbox[(state[row][col] & 0x000000ff)]&0xff); 


 return state; 

 } 


 private static byte[][] ShiftRows(byte[][] state) { 


 byte[] t = new byte[4]; 

 for (int r = 1; r < 4; r++) { 

 for (int c = 0; c < Nb; c++) 

 t[c] = state[r][(c + r) % Nb]; 

 for (int c = 0; c < Nb; c++) 

 state[r][c] = t[c]; 

 } 


 return state; 

 } 


 private static byte[][] InvShiftRows(byte[][] state) { 

 byte[] t = new byte[4]; 

 for (int r = 1; r < 4; r++) { 

 for (int c = 0; c < Nb; c++) 

 t[(c + r)%Nb] = state[r][c]; 

 for (int c = 0; c < Nb; c++) 

 state[r][c] = t[c]; 

 } 

 return state; 

 } 


 private static byte[][] InvMixColumns(byte[][] s){ 

 int[] sp = new int[4]; 

 byte b02 = (byte)0x0e, b03 = (byte)0x0b, b04 = (byte)0x0d, b05 = (byte)0x09; 

 for (int c = 0; c < 4; c++) { 

 sp[0] = FFMul(b02, s[0][c]) ^ FFMul(b03, s[1][c]) ^ FFMul(b04,s[2][c]) ^ FFMul(b05,s[3][c]); 

 sp[1] = FFMul(b05, s[0][c]) ^ FFMul(b02, s[1][c]) ^ FFMul(b03,s[2][c]) ^ FFMul(b04,s[3][c]); 

 sp[2] = FFMul(b04, s[0][c]) ^ FFMul(b05, s[1][c]) ^ FFMul(b02,s[2][c]) ^ FFMul(b03,s[3][c]); 

 sp[3] = FFMul(b03, s[0][c]) ^ FFMul(b04, s[1][c]) ^ FFMul(b05,s[2][c]) ^ FFMul(b02,s[3][c]); 

 for (int i = 0; i < 4; i++) s[i][c] = (byte)(sp[i]); 

 } 


 return s; 

 } 


 private static byte[][] MixColumns(byte[][] s){ 

 int[] sp = new int[4]; 

 byte b02 = (byte)0x02, b03 = (byte)0x03; 

 for (int c = 0; c < 4; c++) { 

 sp[0] = FFMul(b02, s[0][c]) ^ FFMul(b03, s[1][c]) ^ s[2][c] ^ s[3][c]; 

 sp[1] = s[0][c] ^ FFMul(b02, s[1][c]) ^ FFMul(b03, s[2][c]) ^ s[3][c]; 

 sp[2] = s[0][c] ^ s[1][c] ^ FFMul(b02, s[2][c]) ^ FFMul(b03, s[3][c]); 

 sp[3] = FFMul(b03, s[0][c]) ^ s[1][c] ^ s[2][c] ^ FFMul(b02, s[3][c]); 

 for (int i = 0; i < 4; i++) s[i][c] = (byte)(sp[i]); 

 } 


 return s; 

 } 


 public static byte FFMul(byte a, byte b) { 

 byte aa = a, bb = b, r = 0, t; 

 while (aa != 0) { 

 if ((aa & 1) != 0) 

 r = (byte) (r ^ bb); 

 t = (byte) (bb & 0x80); 

 bb = (byte) (bb << 1); 

 if (t != 0) 

 bb = (byte) (bb ^ 0x1b); 

 aa = (byte) ((aa & 0xff) >> 1); 

 } 

 return r; 

 } 


 public static byte[] encryptBloc(byte[] in) { 

 byte[] tmp = new byte[in.length]; 




 byte[][] state = new byte[4][Nb]; 


 for (int i = 0; i < in.length; i++) 

 state[i / 4][i % 4] = in[i%4*4+i/4]; 


 state = AddRoundKey(state, w, 0); 

 for (int round = 1; round < Nr; round++) { 

 state = SubBytes(state); 

 state = ShiftRows(state); 

 state = MixColumns(state); 

 state = AddRoundKey(state, w, round); 

 } 

 state = SubBytes(state); 

 state = ShiftRows(state); 

 state = AddRoundKey(state, w, Nr); 


 for (int i = 0; i < tmp.length; i++) 

 tmp[i%4*4+i/4] = state[i / 4][i%4]; 


 return tmp; 

 } 


 public static byte[] decryptBloc(byte[] in) { 

 byte[] tmp = new byte[in.length]; 


 byte[][] state = new byte[4][Nb]; 


 for (int i = 0; i < in.length; i++) 

 state[i / 4][i % 4] = in[i%4*4+i/4]; 


 state = AddRoundKey(state, w, Nr); 

 for (int round = Nr-1; round >=1; round--) { 

 state = InvSubBytes(state); 

 state = InvShiftRows(state); 

 state = AddRoundKey(state, w, round); 

 state = InvMixColumns(state); 


 } 

 state = InvSubBytes(state); 

 state = InvShiftRows(state); 

 state = AddRoundKey(state, w, 0); 


 for (int i = 0; i < tmp.length; i++) 

 tmp[i%4*4+i/4] = state[i / 4][i%4]; 


 return tmp; 

 } 


 public static byte[] encrypt(byte[] in,byte[] key){ 


 Nb = 4; 

 Nk = key.length/4; 

 Nr = Nk + 6; 



 int lenght=0; 

 /*byte[] padding = new byte[1];*/ 

 int i; 

 /*lenght = 16 - in.length % 16; 

 padding = new byte[lenght]; 

 padding[0] = (byte) 0x80; 


 for (i = 1; i < lenght; i++) 

 padding[i] = 0;*/ 


 byte[] tmp = new byte[in.length + lenght]; 

 byte[] bloc = new byte[16]; 



 w = generateSubkeys(key); 


 int count = 0; 


 for (i = 0; i < in.length + lenght; i++) { 

 if (i > 0 && i % 16 == 0) { 

 bloc = encryptBloc(bloc); 

 System.arraycopy(bloc, 0, tmp, i - 16, bloc.length); 

 } 

 if (i < in.length) 

 bloc[i % 16] = in[i]; 

 /*else{ 

 bloc[i % 16] = padding[count % 16]; 

 count++; 

 }*/ 

 } 

 if(bloc.length == 16){ 

 bloc = encryptBloc(bloc); 

 System.arraycopy(bloc, 0, tmp, i - 16, bloc.length); 

 } 


 return tmp; 

 } 


 public static byte[] decrypt(byte[] in,byte[] key){ 

 int i; 

 byte[] tmp = new byte[in.length]; 

 byte[] bloc = new byte[16]; 



 Nb = 4; 

 Nk = key.length/4; 

 Nr = Nk + 6; 

 w = generateSubkeys(key); 



 for (i = 0; i < in.length; i++) { 

 if (i > 0 && i % 16 == 0) { 

 bloc = decryptBloc(bloc); 

 System.arraycopy(bloc, 0, tmp, i - 16, bloc.length); 

 } 

 if (i < in.length) 

 bloc[i % 16] = in[i]; 

 } 

 bloc = decryptBloc(bloc); 

 System.arraycopy(bloc, 0, tmp, i - 16, bloc.length); 



 /*tmp = deletePadding(tmp);*/ 


 return tmp; 

 } 


 /*private static byte[] deletePadding(byte[] input) { 

 int count = 0; 


 int i = input.length - 1; 

 while (input[i] == 0) { 

 count++; 

 i--; 

 } 


 byte[] tmp = new byte[input.length - count - 1]; 

 System.arraycopy(input, 0, tmp, 0, tmp.length); 

 return tmp; 

 }*/ 


}



C代码
aes.c

/* 


This is an implementation of the AES128 algorithm, specifically ECB mode. 


The implementation is verified against the test vectors in: 

 National Institute of Standards and Technology Special Publication 800-38A 2001 ED 


ECB-AES128 

---------- 


 plain-text: 

 6bc1bee22e409f96e93d7e117393172a 

 ae2d8a571e03ac9c9eb76fac45af8e51 

 30c81c46a35ce411e5fbc1191a0a52ef 

 f69f2445df4f9b17ad2b417be66c3710 


 key: 

 2b7e151628aed2a6abf7158809cf4f3c 


 resulting cipher 

 50fe67cc996d32b6da0937e99bafec60 

 d9a4dada0892239f6b8b3d7680e15674 

 a78819583f0308e7a6bf36b1386abf23 

 c6d3416d29165c6fcb8e51a227ba994e 



NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) 

 You should pad the end of the string with zeros if this is not the case. 


*/ 


#ifndef _AES_C_ 

#define _AES_C_ 



/*****************************************************************************/ 

/* Includes: */ 

/*****************************************************************************/ 

#include <stdint.h> 

#include "aes.h" 



/*****************************************************************************/ 

/* Defines: */ 

/*****************************************************************************/ 

// The number of columns comprising a state in AES. This is a constant in AES. Value=4 

#define Nb 4 

// The number of 32 bit words in a key. 

#define Nk 4 

// Key length in bytes [128 bit] 

#define keyln 16 

// The number of rounds in AES Cipher. 

#define Nr 10 



/*****************************************************************************/ 

/* Private variables: */ 

/*****************************************************************************/ 

// in - pointer to the CipherText to be decrypted. 

// out - pointer to buffer to hold output of the decryption. 

// state - array holding the intermediate results during decryption. 

static uint8_t* in, *out, state[4][4]; 


// The array that stores the round keys. 

static uint8_t RoundKey[176]; 


// The Key input to the AES Program 

static uint8_t* Key; 


// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM 

// The numbers below can be computed dynamically trading ROM for RAM - 

// This can be useful in (embedded) bootloader applications, where ROM is often limited. 

static const uint8_t sbox[256] = { 

 //0 1 2 3 4 5 6 7 8 9 A B C D E F 

 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 

 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 

 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 

 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 

 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 

 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 

 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 

 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 

 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 

 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 

 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 

 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 

 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 

 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 

 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 

 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; 


static const uint8_t rsbox[256] = 

{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb 

, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb 

, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e 

, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 

, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 

, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 

, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 

, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b 

, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 

, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e 

, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b 

, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 

, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f 

, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef 

, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 

, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; 



// The round constant word array, Rcon[i], contains the values given by 

// x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) 

// Note that i starts at 1, not 0). 

static const uint8_t Rcon[255] = { 

 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 

 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 

 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 

 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 

 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 

 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 

 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 

 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 

 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 

 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 

 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 

 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 

 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 

 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 

 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 

 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb }; 



/*****************************************************************************/ 

/* Private functions: */ 

/*****************************************************************************/ 

static uint8_t getSBoxValue(uint8_t num) 

{ 

 return sbox[num]; 

} 


static uint8_t getSBoxInvert(uint8_t num) 

{ 

 return rsbox[num]; 

} 



// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. 

static void KeyExpansion() 

{ 

 uint32_t i, j, k; 

 uint8_t tempa[4]; // used for the column/row operations 


 // The first round key is the key itself. 

 for(i = 0; i < Nk; ++i) 

 { 

 RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; 

 RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; 

 RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; 

 RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; 

 } 


 // All other round keys are found from the previous round keys. 

 for(; (i < (Nb * (Nr + 1))); ++i) 

 { 

 for(j = 0; j < 4; ++j) 

 { 

 tempa[j]=RoundKey[(i-1) * 4 + j]; 

 } 

 if (i % Nk == 0) 

 { 

 // This function rotates the 4 bytes in a word to the left once. 

 // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] 


 // Function RotWord() 

 { 

 k = tempa[0]; 

 tempa[0] = tempa[1]; 

 tempa[1] = tempa[2]; 

 tempa[2] = tempa[3]; 

 tempa[3] = k; 

 } 


 // SubWord() is a function that takes a four-byte input word and 

 // applies the S-box to each of the four bytes to produce an output word. 


 // Function Subword() 

 { 

 tempa[0] = getSBoxValue(tempa[0]); 

 tempa[1] = getSBoxValue(tempa[1]); 

 tempa[2] = getSBoxValue(tempa[2]); 

 tempa[3] = getSBoxValue(tempa[3]); 

 } 


 tempa[0] = tempa[0] ^ Rcon[i/Nk]; 

 } 

 else if (Nk > 6 && i % Nk == 4) 

 { 

 // Function Subword() 

 { 

 tempa[0] = getSBoxValue(tempa[0]); 

 tempa[1] = getSBoxValue(tempa[1]); 

 tempa[2] = getSBoxValue(tempa[2]); 

 tempa[3] = getSBoxValue(tempa[3]); 

 } 

 } 

 RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0]; 

 RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1]; 

 RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2]; 

 RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3]; 

 } 

} 


// This function adds the round key to state. 

// The round key is added to the state by an XOR function. 

static void AddRoundKey(uint8_t round) 

{ 

 uint8_t i,j; 

 for(i=0;i<4;i++) 

 { 

 for(j = 0; j < 4; ++j) 

 { 

 state[j][i] ^= RoundKey[round * Nb * 4 + i * Nb + j]; 

 } 

 } 

} 


// The SubBytes Function Substitutes the values in the 

// state matrix with values in an S-box. 

static void SubBytes() 

{ 

 uint8_t i, j; 

 for(i = 0; i < 4; ++i) 

 { 

 for(j = 0; j < 4; ++j) 

 { 

 state[i][j] = getSBoxValue(state[i][j]); 

 } 

 } 

} 


// The ShiftRows() function shifts the rows in the state to the left. 

// Each row is shifted with different offset. 

// Offset = Row number. So the first row is not shifted. 

static void ShiftRows() 

{ 

 uint8_t temp; 


 // Rotate first row 1 columns to left 

 temp = state[1][0]; 

 state[1][0] = state[1][1]; 

 state[1][1] = state[1][2]; 

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

 state[1][3] = temp; 


 // Rotate second row 2 columns to left 

 temp = state[2][0]; 

 state[2][0] = state[2][2]; 

 state[2][2] = temp; 


 temp = state[2][1]; 

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

 state[2][3] = temp; 


 // Rotate third row 3 columns to left 

 temp = state[3][0]; 

 state[3][0] = state[3][3]; 

 state[3][3] = state[3][2]; 

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

 state[3][1] = temp; 

} 


static uint8_t xtime(uint8_t x) 

{ 

 return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); 

} 


// MixColumns function mixes the columns of the state matrix 

static void MixColumns() 

{ 

 uint8_t i; 

 uint8_t Tmp,Tm,t; 

 for(i = 0; i < 4; ++i) 

 { 

 t = state[0][i]; 

 Tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i] ; 

 Tm = state[0][i] ^ state[1][i] ; Tm = xtime(Tm); state[0][i] ^= Tm ^ Tmp ; 

 Tm = state[1][i] ^ state[2][i] ; Tm = xtime(Tm); state[1][i] ^= Tm ^ Tmp ; 

 Tm = state[2][i] ^ state[3][i] ; Tm = xtime(Tm); state[2][i] ^= Tm ^ Tmp ; 

 Tm = state[3][i] ^ t ; Tm = xtime(Tm); state[3][i] ^= Tm ^ Tmp ; 

 } 

} 


// Multiplty is a macro used to multiply numbers in the field GF(2^8) 

#define Multiply(x,y) (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x)) ^ ((y>>2 & 1) * xtime(xtime(x))) ^ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) 



// MixColumns function mixes the columns of the state matrix. 

// The method used to multiply may be difficult to understand for the inexperienced. 

// Please use the references to gain more information. 

static void InvMixColumns() 

{ 

 int i; 

 uint8_t a,b,c,d; 

 for(i=0;i<4;i++) 

 { 


 a = state[0][i]; 

 b = state[1][i]; 

 c = state[2][i]; 

 d = state[3][i]; 



 state[0][i] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); 

 state[1][i] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); 

 state[2][i] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); 

 state[3][i] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); 

 } 

} 



// The SubBytes Function Substitutes the values in the 

// state matrix with values in an S-box. 

static void InvSubBytes() 

{ 

 uint8_t i,j; 

 for(i=0;i<4;i++) 

 { 

 for(j=0;j<4;j++) 

 { 

 state[i][j] = getSBoxInvert(state[i][j]); 

 } 

 } 

} 



static void InvShiftRows() 

{ 

 uint8_t temp; 


 // Rotate first row 1 columns to right 

 temp=state[1][3]; 

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

 state[1][2]=state[1][1]; 

 state[1][1]=state[1][0]; 

 state[1][0]=temp; 


 // Rotate second row 2 columns to right 

 temp=state[2][0]; 

 state[2][0]=state[2][2]; 

 state[2][2]=temp; 


 temp=state[2][1]; 

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

 state[2][3]=temp; 


 // Rotate third row 3 columns to right 

 temp=state[3][0]; 

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

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

 state[3][2]=state[3][3]; 

 state[3][3]=temp; 

} 



// Cipher is the main function that encrypts the PlainText. 

static void Cipher() 

{ 

 uint8_t i, j, round = 0; 


 //Copy the input PlainText to state array. 

 for(i = 0; i < 4; ++i) 

 { 

 for(j = 0; j < 4 ; ++j) 

 { 

 state[j][i] = in[(i * 4) + j]; 

 } 

 } 


 // Add the First round key to the state before starting the rounds. 

 AddRoundKey(0); 


 // There will be Nr rounds. 

 // The first Nr-1 rounds are identical. 

 // These Nr-1 rounds are executed in the loop below. 

 for(round = 1; round < Nr; ++round) 

 { 

 SubBytes(); 

 ShiftRows(); 

 MixColumns(); 

 AddRoundKey(round); 

 } 


 // The last round is given below. 

 // The MixColumns function is not here in the last round. 

 SubBytes(); 

 ShiftRows(); 

 AddRoundKey(Nr); 


 // The encryption process is over. 

 // Copy the state array to output array. 

 for(i = 0; i < 4; ++i) 

 { 

 for(j = 0; j < 4; ++j) 

 { 

 out[(i * 4) + j] = state[j][i]; 

 } 

 } 

} 


static void InvCipher() 

{ 

 uint8_t i,j,round=0; 


 //Copy the input CipherText to state array. 

 for(i=0;i<4;i++) 

 { 

 for(j=0;j<4;j++) 

 { 

 state[j][i] = in[i*4 + j]; 

 } 

 } 


 // Add the First round key to the state before starting the rounds. 

 AddRoundKey(Nr); 


 // There will be Nr rounds. 

 // The first Nr-1 rounds are identical. 

 // These Nr-1 rounds are executed in the loop below. 

 for(round=Nr-1;round>0;round--) 

 { 

 InvShiftRows(); 

 InvSubBytes(); 

 AddRoundKey(round); 

 InvMixColumns(); 

 } 


 // The last round is given below. 

 // The MixColumns function is not here in the last round. 

 InvShiftRows(); 

 InvSubBytes(); 

 AddRoundKey(0); 


 // The decryption process is over. 

 // Copy the state array to output array. 

 for(i=0;i<4;i++) 

 { 

 for(j=0;j<4;j++) 

 { 

 out[i*4+j]=state[j][i]; 

 } 

 } 

} 



/*****************************************************************************/ 

/* Public functions: */ 

/*****************************************************************************/ 


void AES128_ECB_encrypt(uint8_t* input, uint8_t* key, uint8_t *output) 

{ 

 // Copy the Key and CipherText 

 Key = key; 

 in = input; 

 out = output; 


 // The KeyExpansion routine must be called before encryption. 

 KeyExpansion(); 


 // The next function call encrypts the PlainText with the Key using AES algorithm. 

 Cipher(); 

} 


void AES128_ECB_decrypt(uint8_t* input, uint8_t* key, uint8_t *output) 

{ 

 Key = key; 

 in = input; 

 out = output; 


 KeyExpansion(); 


 InvCipher(); 

} 


#endif //_AES_C_ 



aes.h 

#ifndef _AES_H_ 

#define _AES_H_ 


#include <stdint.h> 


void AES128_ECB_encrypt(uint8_t* input, uint8_t* key, uint8_t *output); 

void AES128_ECB_decrypt(uint8_t* input, uint8_t* key, uint8_t *output); 


#endif //_AES_H_ 


test.c 

#include <stdio.h> 

#include <string.h> 

#include <stdint.h> 

#include "aes.h" 


static void phex(uint8_t* str); 

static void test_ECB(void); 

static void test_decrypt(void); 



int main(int argc, char** argv) 

{ 

 test_ECB(); 

 test_decrypt(); 

 return 0; 

} 



/* Helpers */ 


static void test_ECB(void) 

{ 

 uint8_t i, buf[64], buf2[64]; 


 // 128bit key 

 uint8_t key[16] = { (uint8_t) 0x2b, (uint8_t) 0x7e, (uint8_t) 0x15, (uint8_t) 0x16, (uint8_t) 0x28, (uint8_t) 0xae, (uint8_t) 0xd2, (uint8_t) 0xa6, (uint8_t) 0xab, (uint8_t) 0xf7, (uint8_t) 0x15, (uint8_t) 0x88, (uint8_t) 0x09, (uint8_t) 0xcf, (uint8_t) 0x4f, (uint8_t) 0x3c }; 

 // 512bit text 

 uint8_t plain_text[64] = { (uint8_t) 0x6b, (uint8_t) 0xc1, (uint8_t) 0xbe, (uint8_t) 0xe2, (uint8_t) 0x2e, (uint8_t) 0x40, (uint8_t) 0x9f, (uint8_t) 0x96, (uint8_t) 0xe9, (uint8_t) 0x3d, (uint8_t) 0x7e, (uint8_t) 0x11, (uint8_t) 0x73, (uint8_t) 0x93, (uint8_t) 0x17, (uint8_t) 0x2a, 

 (uint8_t) 0xae, (uint8_t) 0x2d, (uint8_t) 0x8a, (uint8_t) 0x57, (uint8_t) 0x1e, (uint8_t) 0x03, (uint8_t) 0xac, (uint8_t) 0x9c, (uint8_t) 0x9e, (uint8_t) 0xb7, (uint8_t) 0x6f, (uint8_t) 0xac, (uint8_t) 0x45, (uint8_t) 0xaf, (uint8_t) 0x8e, (uint8_t) 0x51, 

 (uint8_t) 0x30, (uint8_t) 0xc8, (uint8_t) 0x1c, (uint8_t) 0x46, (uint8_t) 0xa3, (uint8_t) 0x5c, (uint8_t) 0xe4, (uint8_t) 0x11, (uint8_t) 0xe5, (uint8_t) 0xfb, (uint8_t) 0xc1, (uint8_t) 0x19, (uint8_t) 0x1a, (uint8_t) 0x0a, (uint8_t) 0x52, (uint8_t) 0xef, 

 (uint8_t) 0xf6, (uint8_t) 0x9f, (uint8_t) 0x24, (uint8_t) 0x45, (uint8_t) 0xdf, (uint8_t) 0x4f, (uint8_t) 0x9b, (uint8_t) 0x17, (uint8_t) 0xad, (uint8_t) 0x2b, (uint8_t) 0x41, (uint8_t) 0x7b, (uint8_t) 0xe6, (uint8_t) 0x6c, (uint8_t) 0x37, (uint8_t) 0x10 }; 


 memset(buf, 0, 64); 

 memset(buf2, 0, 64); 


 // print text to encrypt, key and IV 

 printf("plain text:\n"); 

 for(i = (uint8_t) 0; i < (uint8_t) 4; ++i) 

 { 

 phex(plain_text + i * (uint8_t) 16); 

 } 

 printf("\n"); 


 printf("key:\n"); 

 phex(key); 

 printf("\n"); 


 // print the resulting cipher as 4 x 16 byte strings 

 printf("ciphertext:\n"); 

 for(i = 0; i < 4; ++i) 

 { 

 AES128_ECB_encrypt(plain_text + (i*16), key, buf+(i*16)); 

 phex(buf + (i*16)); 

 } 

 printf("\n"); 

} 


// prints string as hex 

static void phex(uint8_t* str) 

{ 

 unsigned char i; 

 for(i = 0; i < 16; ++i) 

 printf("%.2x", str[i]); 

 printf("\n"); 

} 



static void test_decrypt(void) 

{ 

 uint8_t key[] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; 

 uint8_t in[] = {0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97}; 

 uint8_t out[] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}; 

 uint8_t buffer[16]; 


 AES128_ECB_decrypt(in, key, buffer); 


 printf("decrypt: "); 


 if(0 == strncmp(out, buffer, 16)) 

 { 

 printf("SUCCESS!\n"); 

 } 

 else 

 { 

 printf("FAILURE!\n"); 

 } 

} 


Makefile 

#CC = avr-gcc 

#CFLAGS = -Wall -mmcu=atmega16 -Os -Wl,-Map,test.map 

#OBJCOPY = avr-objcopy 

CC = gcc 

CFLAGS = -Wall -Os -Wl,-Map,test.map 

OBJCOPY = objcopy 


# include path to AVR library 

INCLUDE_PATH = /usr/lib/avr/include 

# splint static check 

SPLINT = splint test.c aes.c -I$(INCLUDE_PATH) +charindex -unrecog 


.SILENT: 

.PHONY: lint clean 



rom.hex : test.out 

 # copy object-code to new image and format in hex 

 $(OBJCOPY) -j .text -O ihex test.out rom.hex 


test.o : test.c 

 # compiling test.c 

 $(CC) $(CFLAGS) -c test.c -o test.o 


aes.o : aes.h aes.c 

 # compiling aes.c 

 $(CC) $(CFLAGS) -c aes.c -o aes.o 


test.out : aes.o test.o 

 # linking object code to binary 

 $(CC) $(CFLAGS) aes.o test.o -o test.out 


small: test.out 

 $(OBJCOPY) -j .text -O ihex test.out rom.hex 


clean: 

 rm -f *.OBJ *.LST *.o *.gch *.out *.hex *.map 


lint: 

 $(call SPLINT) 


README.md 

### Tiny AES128 in C 


This is a small and portable implementation of the AES128 ECB encryption algorithm implemented in C. 


The API is very simple and looks like this (I am using C99 `<stdint.h>`-style annotated types): 


```C 

void AES128_ECB_encrypt(uint8_t* input, uint8_t* key, uint8_t *output); 

void AES128_ECB_decrypt(uint8_t* input, uint8_t* key, uint8_t *output); 

``` 


The module uses just a bit more than 200 bytes of RAM and 2.5K ROM when compiled for ARM (~2K for Thumb but YMMV). 


It is the smallest implementation in C I've seen yet, but do contact me if you know of something smaller (or have improvements to the code here). 



I've successfully used the code on 64bit x86, 32bit ARM and 8 bit AVR platforms. 



GCC size output when compiled for ARM: 



 $ arm-none-eabi-gcc -Os -c aes.c 

 $ size aes.o 

 text data bss dec hex filename 

 2515 0 204 2719 a9f aes.o 



.. and when compiling for the THUMB instruction set, we end up around 2K in code size. 


 $ arm-none-eabi-gcc -mthumb -Os -c aes.c 

 $ size aes.o 

 text data bss dec hex filename 

 1883 0 204 2087 827 aes.o 



I am using Mentor Graphics free ARM toolchain: 



 $ arm-none-eabi-gcc --version 

 arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.8.4 20140526 (release) [ARM/embedded-4_8-branch revision 211358] 

 Copyright (C) 2013 Free Software Foundation, Inc. 

 This is free software; see the source for copying conditions. There is NO 

 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 



This implementation is verified against the data in: 


[National Institute of Standards and Technology Special Publication 800-38A 2001 ED](http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf) Appendix F: Example Vectors for Modes of Operation of the AES. 



All material in this repository is in the public domain.



见github 地址