diff --git a/aes128.c b/aes128.c new file mode 100644 index 0000000..ce8d169 --- /dev/null +++ b/aes128.c @@ -0,0 +1,206 @@ +/* SensorBoard Secure Library + * Subject: AES implementation from FIPS 197 + * (http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf) + * Copyright (C) 2015, T.Kurosawa + */ +#include +#include +#include "aes128.h" + +#include "aes128_sbox.h" + +static int w[60]; // FIPS 197 P.19 5.2 Key Expansion + +const int Nb = 4; + +static const int nround = aes_keylen_i + 6; + +// local functions ... + +// FIPS 197 P.20 Figure 11 +// FIPS 197 P.19 5.2 +static int SubWord(uint in) +{ + return (((Sbox[(in ) & 0xff]) ) | + ((Sbox[(in >> 8) & 0xff]) << 8) | + ((Sbox[(in >> 16) & 0xff]) << 16) | + ((Sbox[(in >> 24) & 0xff]) << 24) ); +} +// FIPS 197 P.16 Figure 6 +static void SubBytes(uint data[]) +{ + int i; + for (i = 0; i< Nb; i++) + data[i] = SubWord(data[i]); +} +// FIPS 197 P.20 Figure 11 +// FIPS 197 P.19 5.2 +static int invSubWord(uint in) +{ + return (((invSbox[(in ) & 0xff]) ) | + ((invSbox[(in >> 8) & 0xff]) << 8) | + ((invSbox[(in >> 16) & 0xff]) << 16) | + ((invSbox[(in >> 24) & 0xff]) << 24) ); +} +// FIPS 197 P.22 5.3.2 +static void invSubBytes(uint data[]) +{ + int i; + for (i = 0; i< Nb; i++) + data[i] = invSubWord(data[i]); +} +// FIPS 197 P.20 Figure 11 +// FIPS 197 P.19 5.2 +static int RotWord(int in) +{ + return (((in & 0xff000000)>> 8) | + ((in & 0x00ff0000)>> 8) | + ((in & 0x0000ff00)>> 8) | + ((in & 0x000000ff)<<24) ); +} +// FIPS 197 P.20 Figure 11 +// FIPS 197 P.19 5.2 +static void KeyExpansion(void *key) +{ + // FIPS 197 P.27 Appendix A.1 + int Rcon[10] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36}; + int i, temp; + + memcpy(w, key, aes_keylen); + for (i = aes_keylen_i; i< 4*(nround+1); i++) { + temp = w[i-1]; + if ((i % aes_keylen_i) == 0) + temp = SubWord(RotWord(temp)) ^ Rcon[(i/aes_keylen_i)-1]; + w[i] = w[i-aes_keylen_i] ^ temp; + } +} +// FIPS 197 P.10 4.2 poly-multiply +static int mul(int dt, int n) +{ + int i, x = 0; + for (i = 8; i >0; i>>=1) { + x <<= 1; + if (x & 0x100) x = (x ^ 0x1b) & 0xff; + if (n & i) x ^= dt; + } + return x; +} +// FIPS 197 P.18 Figure 9 +static void MixColumns(uint data[]) +{ + int i; + uint8 *p = (uint8 *) data; + for (i = 0; i< Nb; i++) { + int idx = i<<2, x; + x = mul(p[idx+0], 2) ^ mul(p[idx+1], 3) ^ + mul(p[idx+2], 1) ^ mul(p[idx+3], 1); + x |= (mul(p[idx+1], 2) ^ mul(p[idx+2], 3) ^ + mul(p[idx+3], 1) ^ mul(p[idx+0], 1)) << 8; + x |= (mul(p[idx+2], 2) ^ mul(p[idx+3], 3) ^ + mul(p[idx+0], 1) ^ mul(p[idx+1], 1)) << 16; + x |= (mul(p[idx+3], 2) ^ mul(p[idx+0], 3) ^ + mul(p[idx+1], 1) ^ mul(p[idx+2], 1)) << 24; + data[i] = x; + } +} +// FIPS 197 P.23 5.3.3 +static void invMixColumns(uint data[], int n) +{ + int i; + uint8 *p = (uint8 *) data; + for (i = 0; i< Nb; i++) { + int idx = i<<2, x; + x = mul(p[idx+0], 14) ^ mul(p[idx+1], 11) ^ + mul(p[idx+2], 13) ^ mul(p[idx+3], 9); + x |= (mul(p[idx+1], 14) ^ mul(p[idx+2], 11) ^ + mul(p[idx+3], 13) ^ mul(p[idx+0], 9)) << 8; + x |= (mul(p[idx+2], 14) ^ mul(p[idx+3], 11) ^ + mul(p[idx+0], 13) ^ mul(p[idx+1], 9)) << 16; + x |= (mul(p[idx+3], 14) ^ mul(p[idx+0], 11) ^ + mul(p[idx+1], 13) ^ mul(p[idx+2], 9)) << 24; + data[i] = x; + } +} +// FIPS 197 P.17 Figure 8 +static void ShiftRows(uint data[]) +{ + int i; + uint8 *p=(uint8 *)data; + uint8 temp[aes_datalen]; + + for (i = 0; i< aes_datalen; i++) { + int r = (i/4), c = i & 3; + int from = (r*4+(c*5)) & 15; + temp[i] = p[from]; + } + memcpy(p, temp, aes_datalen); +} +// FIPS 197 P.22 Figure 13 +static void invShiftRows(uint data[]) +{ + int i; + uint8 *p=(uint8 *)data; + uint8 temp[aes_datalen]; + + for (i = 0; i< aes_datalen; i++) { + int r = (i/4), c = i & 3; + int to = (r*4+(c*5)) & 15; + temp[to] = p[i]; + } + memcpy(p, temp, aes_datalen); +} +// FIPS 197 P.19 Figure 10 +static void AddRoundKey(uint data[], int n) +{ + int i; + for (i = 0; i< aes_datalen_i; i++) { + data[i] ^= w[i+n*Nb]; + } +} + +////// exported function +// encrypt() +int AES128_crypt(uint data[], uint8 *key) +{ + int i; + + KeyExpansion(key); + + AddRoundKey(data, 0); + + for (i = 1; i< nround; i++) { + SubBytes(data); + ShiftRows(data); + MixColumns(data); + AddRoundKey(data, i); + } + + SubBytes(data); + ShiftRows(data); + AddRoundKey(data, i); + return i; +} + +////// exported function +// decrypt() +int AES128_decrypt(uint data[], uint8 *key) +{ + int i; + + AddRoundKey(data, nround); + + for (i = nround-1; i >0; i--) { + invShiftRows(data); + invSubBytes(data); + AddRoundKey(data, i); + invMixColumns(data, i); + } + + invShiftRows(data); + invSubBytes(data); + AddRoundKey(data, 0); + return nround; +} + +// O.M.A.J.I.N.A.I. +// vi:expandtab:foldmethod=syntax sw=2 ts=2 diff --git a/aes128.h b/aes128.h new file mode 100644 index 0000000..a38d58e --- /dev/null +++ b/aes128.h @@ -0,0 +1,20 @@ +#ifndef __SECURE_AES128__ +#define __SECURE_AES128__ + +#include "secure_types.h" + +static const int aes_datalen_in_bit = 128; +static const int aes_datalen = aes_datalen_in_bit/8; +static const int aes_datalen_i = aes_datalen/sizeof(int); + +static const int aes_keylen_in_bit = 128; +static const int aes_keylen = aes_keylen_in_bit/8; +static const int aes_keylen_i = aes_keylen/sizeof(int); + + +int AES128_crypt(uint data[], uint8 *key); +int AES128_decrypt(uint data[], uint8 *key); + +// vi:expandtab:foldmethod=syntax sw=2 ts=2 + +#endif/*__SECURE_AES128__*/ diff --git a/aes128_sbox.h b/aes128_sbox.h new file mode 100644 index 0000000..43afcd1 --- /dev/null +++ b/aes128_sbox.h @@ -0,0 +1,49 @@ +/* SensorBoard Secure Library + * Subject: AES SBox + * (http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf) + * Copyright (C) 2015, T.Kurosawa + */ + +/************************************************************/ +/* FIPS 197 P.16 Figure 7 */ +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, +}; + +/************************************************************/ +/* FIPS 197 P.22 Figure 14 */ +int invSbox[] = { + 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, +}; + + diff --git a/aes_cmac.c b/aes_cmac.c new file mode 100644 index 0000000..fdd96eb --- /dev/null +++ b/aes_cmac.c @@ -0,0 +1,108 @@ +/* SensorBoard Secure Library + * Subject: AES-CMAC implementation from IETF RFC 4493 + * (http://tools.ietf.org/html/rfc4493) + * Copyright (C) 2015, T.Kurosawa + */ +#include + +#include "aes_cmac.h" +#include "aes128.h" + +static uint mac[aes_datalen_i]; +static uint K1[aes_datalen_i]; +static uint K2[aes_datalen_i]; + +static const uint const_Zero[] = + {0x00000000, 0x00000000, 0x00000000, 0x00000000 }; + +static const uint8 const_Rb[] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }; + +/// operators +static void ShiftCopy(uint *to, uint *from) +{ + int i, carry = 0; + for (i = aes_datalen_i-1; i>= 0; i--) { + to[i] = from[i] << 1 | carry; + carry = (from[i] & (1<<31))? 1: 0; + } +} + +static void Xor(uint *a, const uint *b) +{ + int i; + for (i = 0; i< aes_datalen_i; i++) { + a[i] ^= b[i]; + } +} + +static int ceil(int a, int b) +{ + return (a/b)+(((a % b)!=0)?1:0); +} + +static void padding(uint *P, int len) +{ + int i; + uint8 *p = (uint8 *)P; + + len %= aes_datalen; + p[len] = 0x80; + for (i = len+1; i< aes_datalen; i++) { + p[i] = 0x00; + } +} + + +/// sub function +void Generate_Subkey(uint8 *key) +{ + uint L[aes_datalen_i]; + + memcpy(L, const_Zero, sizeof(L)); + AES128_crypt(L, key); + + ShiftCopy(K1, L); + if ((L[0] & (1<<31)) != 0) Xor(K1, (uint *)const_Rb); + + ShiftCopy(K2, K1); + if ((K1[0] & (1<<31)) != 0) Xor(K2, (uint *)const_Rb); +} + +/// exported function +uint *AES_cmac(uint8 *K, uint *M, int len) +{ + uint M_last[aes_datalen_i]; + int n = ceil(len, aes_datalen); + int i, flag; + + Generate_Subkey(K); + + if (len == 0) + flag = 0; + else + flag = ((len % aes_datalen) == 0)? 1: 0; + + if (flag) { + memcpy(M_last, M+(n-1)*aes_datalen_i, aes_datalen); + Xor(M_last, K1); + } else { + memcpy(M_last, M+(n-1)*aes_datalen_i, (len % aes_datalen)); + padding(M_last, len); + Xor(M_last, K2); + } + memcpy(mac, const_Zero, sizeof(mac)); + for (i = 0; i< n-1; i++) { + Xor(mac, M+i*4); + AES128_crypt(mac, K); + } + Xor(mac, M_last); + AES128_crypt(mac, K); + return mac; +} + +// O.M.A.J.I.N.A.I. +// vi:expandtab:foldmethod=syntax sw=2 ts=2 diff --git a/aes_cmac.h b/aes_cmac.h new file mode 100644 index 0000000..623c556 --- /dev/null +++ b/aes_cmac.h @@ -0,0 +1,9 @@ +#ifndef __AES_CMAC__ +#define __AES_CMAC__ + +#include "secure_types.h" +#include "aes128.h" + +uint *AES_cmac(uint8 *key, uint *msg, int len); + +#endif/*__AES_CMAC__*/ diff --git a/aes_kdf.c b/aes_kdf.c new file mode 100644 index 0000000..6abc6e0 --- /dev/null +++ b/aes_kdf.c @@ -0,0 +1,38 @@ +/* SensorBoard Secure Library + * Subject: AES-PDF Miyaguchi-Preneel implementation + * (http://tools.ietf.org/html/rfc4493) + * Copyright (C) 2015, T.Kurosawa + */ +#include +#include "aes_kdf.h" + +static const uint const_Zero[4] = {0, 0, 0, 0}; +static uint H[aes_datalen_i]; + +/// operators +static void Xor(uint *a, const uint *b) +{ + int i; + for (i = 0; i< aes_datalen_i; i++) { + a[i] ^= b[i]; + } +} + +/// exported function +uint *AES_KDF(uint *M, int block_size) +{ + int i; + uint temp[aes_datalen_i]; + + memcpy(H, const_Zero, sizeof(H)); + for (i = 0; i< block_size; i++) { + memcpy(temp, M+i*4, aes_datalen); + AES128_crypt(temp, (uint8 *)H); + Xor(temp, M+i); + Xor(H, temp); + } + return H; +} + +// O.M.A.J.I.N.A.I. +// vi:expandtab:foldmethod=syntax sw=2 ts=2 diff --git a/aes_kdf.h b/aes_kdf.h new file mode 100644 index 0000000..43ed93c --- /dev/null +++ b/aes_kdf.h @@ -0,0 +1,9 @@ +#ifndef __AES_KDF__ +#define __AES_KDF__ + +#include "secure_types.h" +#include "aes128.h" + +uint *AES_KDF(uint *msg, int block_size); + +#endif/*__AES_KDF__*/ diff --git a/secure_types.h b/secure_types.h new file mode 100644 index 0000000..d822dd0 --- /dev/null +++ b/secure_types.h @@ -0,0 +1,33 @@ +#ifndef __SECURE_TYPES__ +#define __SECURE_TYPES__ + +typedef unsigned int uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; + +typedef unsigned int uint; + +union u128 { + uint8 uc[16]; + uint16 us[8]; + uint32 ul[4]; +}; + +typedef uint32 IDATNUM; +typedef uint8 KEY_ID; +typedef union u128 IDAT; +typedef union u128 IV; +typedef union u128 ODAT; +typedef uint32 KEY; +typedef union u128 KEY128; +typedef uint32 KEY_FLG; +typedef uint32 M1; +typedef uint32 M2; +typedef uint32 M3; +typedef uint32 M4; +typedef uint32 M5; +typedef uint32 UID; +typedef uint32 AUTHKEY_ID; + +#endif/*__SECURE_TYPES__*/ +