Add: NRF24L01 AES Encryption
Thanks @fleinze. Source: https://github.com/fleinze/MySensors/tree/Encryption/libraries/MySensors
This commit is contained in:
@@ -193,6 +193,16 @@
|
||||
/**********************************
|
||||
* NRF24L01 Driver Defaults
|
||||
***********************************/
|
||||
|
||||
// Enables RF24 encryption (all nodes and gateway must have this enabled)
|
||||
//#define MY_RF24_ENABLE_ENCRYPTION
|
||||
|
||||
// Default encrytion key. Override in sketch if needed.
|
||||
#ifndef MY_RF24_CE_PIN
|
||||
#define MY_RF24_ENCRYPTKEY 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16
|
||||
#endif
|
||||
|
||||
// Default pin settings. Override in sketch if needed.
|
||||
#ifndef MY_RF24_CE_PIN
|
||||
#define MY_RF24_CE_PIN 9
|
||||
#endif
|
||||
|
||||
@@ -179,6 +179,9 @@
|
||||
#error Only one radio driver can be activated
|
||||
#endif
|
||||
#if defined(MY_RADIO_NRF24)
|
||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||
#include "drivers/AES/AES.cpp"
|
||||
#endif
|
||||
#include "drivers/RF24/RF24.cpp"
|
||||
#include "core/MyTransportNRF24.cpp"
|
||||
#elif defined(MY_RADIO_RFM69)
|
||||
|
||||
@@ -22,6 +22,11 @@
|
||||
RF24 _rf24(MY_RF24_CE_PIN, MY_RF24_CS_PIN);
|
||||
uint8_t _address;
|
||||
uint8_t _paLevel;
|
||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||
AES _aes;
|
||||
uint8_t _dataenc[32] = {0};
|
||||
uint8_t _psk[] = { MY_RF24_ENCRYPTKEY };
|
||||
#endif
|
||||
|
||||
bool transportInit() {
|
||||
// Start up the radio library
|
||||
@@ -42,6 +47,12 @@ bool transportInit() {
|
||||
|
||||
// All nodes listen to broadcast pipe (for FIND_PARENT_RESPONSE messages)
|
||||
_rf24.openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS));
|
||||
|
||||
|
||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||
_aes.set_key(_psk, 16); //set up AES-key
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -57,11 +68,23 @@ uint8_t transportGetAddress() {
|
||||
}
|
||||
|
||||
bool transportSend(uint8_t to, const void* data, uint8_t len) {
|
||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||
memcpy(_dataenc,data,len); // copy input data because it is read-only
|
||||
|
||||
_aes.set_IV(0);//not sure if necessary
|
||||
len = len > 16 ? 32 : 16;
|
||||
_aes.cbc_encrypt(_dataenc, _dataenc, len/16); //encrypt
|
||||
#endif
|
||||
|
||||
// Make sure radio has powered up
|
||||
_rf24.powerUp();
|
||||
_rf24.stopListening();
|
||||
_rf24.openWritingPipe(TO_ADDR(to));
|
||||
bool ok = _rf24.write(data, len, to == BROADCAST_ADDRESS);
|
||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||
bool ok = _rf24.write(_dataenc, len, to == BROADCAST_ADDRESS);
|
||||
#else
|
||||
bool ok = _rf24.write(data, len, to == BROADCAST_ADDRESS);
|
||||
#endif
|
||||
_rf24.startListening();
|
||||
return ok;
|
||||
}
|
||||
@@ -80,6 +103,10 @@ bool transportAvailable(uint8_t *to) {
|
||||
uint8_t transportReceive(void* data) {
|
||||
uint8_t len = _rf24.getDynamicPayloadSize();
|
||||
_rf24.read(data, len);
|
||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||
_aes.set_IV(0);//not sure if necessary
|
||||
_aes.cbc_decrypt((byte*)(data), (byte*)(data), len>16?2:1); // decrypt
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#include <stdint.h>
|
||||
#include "drivers/RF24/RF24.h"
|
||||
#include "drivers/RF24/RF24_config.h"
|
||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||
#include "drivers/AES/AES.h"
|
||||
#endif
|
||||
|
||||
#define TO_ADDR(x) (MY_RF24_BASE_RADIO_ID + x)
|
||||
|
||||
|
||||
@@ -0,0 +1,598 @@
|
||||
#include "AES.h"
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
1. source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
2. binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation;
|
||||
|
||||
3. the name of the copyright holder is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue 09/09/2006
|
||||
|
||||
This is an AES implementation that uses only 8-bit byte operations on the
|
||||
cipher state (there are options to use 32-bit types if available).
|
||||
|
||||
The combination of mix columns and byte substitution used here is based on
|
||||
that developed by Karl Malbrain. His contribution is acknowledged.
|
||||
*/
|
||||
|
||||
/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down
|
||||
and tailored to 8-bit microcontroller abilities and Arduino datatypes.
|
||||
|
||||
The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all
|
||||
the other transformations are coded to save table space. Many efficiency
|
||||
improvments to the routines mix_sub_columns() and inv_mix_sub_columns()
|
||||
(mainly common sub-expression elimination).
|
||||
|
||||
Only the routines with precalculated subkey schedule are retained (together
|
||||
with set_key() - this does however mean each AES object takes 240 bytes of
|
||||
RAM, alas)
|
||||
|
||||
The CBC routines side-effect the iv argument (so that successive calls work
|
||||
together correctly).
|
||||
|
||||
All the encryption and decryption routines work with plain == cipher for
|
||||
in-place encryption, note.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* functions for finite field multiplication in the AES Galois field */
|
||||
|
||||
/* code was modified by george spanos <spaniakos@gmail.com>
|
||||
* 16/12/14
|
||||
*/
|
||||
|
||||
// GF(2^8) stuff
|
||||
|
||||
#define WPOLY 0x011B
|
||||
#define DPOLY 0x008D
|
||||
|
||||
const static byte s_fwd [0x100] PROGMEM =
|
||||
{
|
||||
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,
|
||||
} ;
|
||||
|
||||
const static byte s_inv [0x100] PROGMEM =
|
||||
{
|
||||
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,
|
||||
} ;
|
||||
|
||||
// times 2 in the GF(2^8)
|
||||
#define f2(x) ((x) & 0x80 ? (x << 1) ^ WPOLY : x << 1)
|
||||
#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
|
||||
|
||||
static byte s_box (byte x)
|
||||
{
|
||||
// return fwd_affine (pgm_read_byte (&inv [x])) ;
|
||||
return pgm_read_byte (& s_fwd [x]) ;
|
||||
}
|
||||
|
||||
// Inverse Sbox
|
||||
static byte is_box (byte x)
|
||||
{
|
||||
// return pgm_read_byte (&inv [inv_affine (x)]) ;
|
||||
return pgm_read_byte (& s_inv [x]) ;
|
||||
}
|
||||
|
||||
|
||||
static void xor_block (byte * d, byte * s)
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += 4)
|
||||
{
|
||||
*d++ ^= *s++ ; // some unrolling
|
||||
*d++ ^= *s++ ;
|
||||
*d++ ^= *s++ ;
|
||||
*d++ ^= *s++ ;
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_and_key (byte * d, byte * s, byte * k)
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += 4)
|
||||
{
|
||||
*d++ = *s++ ^ *k++ ; // some unrolling
|
||||
*d++ = *s++ ^ *k++ ;
|
||||
*d++ = *s++ ^ *k++ ;
|
||||
*d++ = *s++ ^ *k++ ;
|
||||
}
|
||||
}
|
||||
|
||||
// #define add_round_key(d, k) xor_block (d, k)
|
||||
|
||||
/* SUB ROW PHASE */
|
||||
|
||||
static void shift_sub_rows (byte st [N_BLOCK])
|
||||
{
|
||||
st [0] = s_box (st [0]) ; st [4] = s_box (st [4]) ;
|
||||
st [8] = s_box (st [8]) ; st [12] = s_box (st [12]) ;
|
||||
|
||||
byte tt = st [1] ;
|
||||
st [1] = s_box (st [5]) ; st [5] = s_box (st [9]) ;
|
||||
st [9] = s_box (st [13]) ; st [13] = s_box (tt) ;
|
||||
|
||||
tt = st[2] ; st [2] = s_box (st [10]) ; st [10] = s_box (tt) ;
|
||||
tt = st[6] ; st [6] = s_box (st [14]) ; st [14] = s_box (tt) ;
|
||||
|
||||
tt = st[15] ;
|
||||
st [15] = s_box (st [11]) ; st [11] = s_box (st [7]) ;
|
||||
st [7] = s_box (st [3]) ; st [3] = s_box (tt) ;
|
||||
}
|
||||
|
||||
static void inv_shift_sub_rows (byte st[N_BLOCK])
|
||||
{
|
||||
st [0] = is_box (st[0]) ; st [4] = is_box (st [4]);
|
||||
st [8] = is_box (st[8]) ; st [12] = is_box (st [12]);
|
||||
|
||||
byte tt = st[13] ;
|
||||
st [13] = is_box (st [9]) ; st [9] = is_box (st [5]) ;
|
||||
st [5] = is_box (st [1]) ; st [1] = is_box (tt) ;
|
||||
|
||||
tt = st [2] ; st [2] = is_box (st [10]) ; st [10] = is_box (tt) ;
|
||||
tt = st [6] ; st [6] = is_box (st [14]) ; st [14] = is_box (tt) ;
|
||||
|
||||
tt = st [3] ;
|
||||
st [3] = is_box (st [7]) ; st [7] = is_box (st [11]) ;
|
||||
st [11] = is_box (st [15]) ; st [15] = is_box (tt) ;
|
||||
}
|
||||
|
||||
/* SUB COLUMNS PHASE */
|
||||
|
||||
static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
||||
{
|
||||
byte j = 5 ;
|
||||
byte k = 10 ;
|
||||
byte l = 15 ;
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += N_COL)
|
||||
{
|
||||
byte a = st [i] ;
|
||||
byte b = st [j] ; j = (j+N_COL) & 15 ;
|
||||
byte c = st [k] ; k = (k+N_COL) & 15 ;
|
||||
byte d = st [l] ; l = (l+N_COL) & 15 ;
|
||||
byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ;
|
||||
byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
|
||||
dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ;
|
||||
dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ;
|
||||
dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ;
|
||||
dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ;
|
||||
}
|
||||
}
|
||||
|
||||
static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += N_COL)
|
||||
{
|
||||
byte a1 = st [i] ;
|
||||
byte b1 = st [i+1] ;
|
||||
byte c1 = st [i+2] ;
|
||||
byte d1 = st [i+3] ;
|
||||
byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
|
||||
byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ;
|
||||
byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ;
|
||||
byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ;
|
||||
byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ;
|
||||
|
||||
dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ;
|
||||
dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ;
|
||||
dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ;
|
||||
dt[(i+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
AES::AES(){
|
||||
byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
|
||||
memcpy(iv,ar_iv,8);
|
||||
memcpy(iv+8,ar_iv,8);
|
||||
arr_pad[0] = 0x01;
|
||||
arr_pad[1] = 0x02;
|
||||
arr_pad[2] = 0x03;
|
||||
arr_pad[3] = 0x04;
|
||||
arr_pad[4] = 0x05;
|
||||
arr_pad[5] = 0x06;
|
||||
arr_pad[6] = 0x07;
|
||||
arr_pad[7] = 0x08;
|
||||
arr_pad[8] = 0x09;
|
||||
arr_pad[9] = 0x0a;
|
||||
arr_pad[10] = 0x0b;
|
||||
arr_pad[11] = 0x0c;
|
||||
arr_pad[12] = 0x0d;
|
||||
arr_pad[13] = 0x0e;
|
||||
arr_pad[14] = 0x0f;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
byte AES::set_key (byte key [], int keylen)
|
||||
{
|
||||
byte hi ;
|
||||
switch (keylen)
|
||||
{
|
||||
case 16:
|
||||
case 128:
|
||||
keylen = 16; // 10 rounds
|
||||
round = 10 ;
|
||||
break;
|
||||
case 24:
|
||||
case 192:
|
||||
keylen = 24; // 12 rounds
|
||||
round = 12 ;
|
||||
break;
|
||||
case 32:
|
||||
case 256:
|
||||
keylen = 32; // 14 rounds
|
||||
round = 14 ;
|
||||
break;
|
||||
default:
|
||||
round = 0;
|
||||
return AES_FAILURE;
|
||||
}
|
||||
hi = (round + 1) << 4 ;
|
||||
copy_n_bytes (key_sched, key, keylen) ;
|
||||
byte t[4] ;
|
||||
byte next = keylen ;
|
||||
for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL)
|
||||
{
|
||||
for (byte i = 0 ; i < N_COL ; i++)
|
||||
t[i] = key_sched [cc-4+i] ;
|
||||
if (cc == next)
|
||||
{
|
||||
next += keylen ;
|
||||
byte ttt = t[0] ;
|
||||
t[0] = s_box (t[1]) ^ rc ;
|
||||
t[1] = s_box (t[2]) ;
|
||||
t[2] = s_box (t[3]) ;
|
||||
t[3] = s_box (ttt) ;
|
||||
rc = f2 (rc) ;
|
||||
}
|
||||
else if (keylen == 32 && (cc & 31) == 16)
|
||||
{
|
||||
for (byte i = 0 ; i < 4 ; i++)
|
||||
t[i] = s_box (t[i]) ;
|
||||
}
|
||||
byte tt = cc - keylen ;
|
||||
for (byte i = 0 ; i < N_COL ; i++)
|
||||
key_sched [cc + i] = key_sched [tt + i] ^ t[i] ;
|
||||
}
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::clean ()
|
||||
{
|
||||
for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++)
|
||||
key_sched [i] = 0 ;
|
||||
round = 0 ;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::copy_n_bytes (byte * d, byte * s, byte nn)
|
||||
{
|
||||
while (nn >= 4)
|
||||
{
|
||||
*d++ = *s++ ; // some unrolling
|
||||
*d++ = *s++ ;
|
||||
*d++ = *s++ ;
|
||||
*d++ = *s++ ;
|
||||
nn -= 4 ;
|
||||
}
|
||||
while (nn--)
|
||||
*d++ = *s++ ;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
|
||||
{
|
||||
if (round)
|
||||
{
|
||||
byte s1 [N_BLOCK], r ;
|
||||
copy_and_key (s1, plain, (byte*) (key_sched)) ;
|
||||
|
||||
for (r = 1 ; r < round ; r++)
|
||||
{
|
||||
byte s2 [N_BLOCK] ;
|
||||
mix_sub_columns (s2, s1) ;
|
||||
copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ;
|
||||
}
|
||||
shift_sub_rows (s1) ;
|
||||
copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ;
|
||||
}
|
||||
else
|
||||
return AES_FAILURE ;
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK])
|
||||
{
|
||||
while (n_block--)
|
||||
{
|
||||
xor_block (iv, plain) ;
|
||||
if (encrypt (iv, iv) != AES_SUCCESS)
|
||||
return AES_FAILURE ;
|
||||
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
||||
plain += N_BLOCK ;
|
||||
cipher += N_BLOCK ;
|
||||
}
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
|
||||
{
|
||||
while (n_block--)
|
||||
{
|
||||
xor_block (iv, plain) ;
|
||||
if (encrypt (iv, iv) != AES_SUCCESS)
|
||||
return AES_FAILURE ;
|
||||
copy_n_bytes (cipher, iv, N_BLOCK) ;
|
||||
plain += N_BLOCK ;
|
||||
cipher += N_BLOCK ;
|
||||
}
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
|
||||
{
|
||||
if (round)
|
||||
{
|
||||
byte s1 [N_BLOCK] ;
|
||||
copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ;
|
||||
inv_shift_sub_rows (s1) ;
|
||||
|
||||
for (byte r = round ; --r ; )
|
||||
{
|
||||
byte s2 [N_BLOCK] ;
|
||||
copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ;
|
||||
inv_mix_sub_columns (s1, s2) ;
|
||||
}
|
||||
copy_and_key (cipher, s1, (byte*) (key_sched)) ;
|
||||
}
|
||||
else
|
||||
return AES_FAILURE ;
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK])
|
||||
{
|
||||
while (n_block--)
|
||||
{
|
||||
byte tmp [N_BLOCK] ;
|
||||
copy_n_bytes (tmp, cipher, N_BLOCK) ;
|
||||
if (decrypt (cipher, plain) != AES_SUCCESS)
|
||||
return AES_FAILURE ;
|
||||
xor_block (plain, iv) ;
|
||||
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
||||
plain += N_BLOCK ;
|
||||
cipher += N_BLOCK;
|
||||
}
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
|
||||
{
|
||||
while (n_block--)
|
||||
{
|
||||
byte tmp [N_BLOCK] ;
|
||||
copy_n_bytes (tmp, cipher, N_BLOCK) ;
|
||||
if (decrypt (cipher, plain) != AES_SUCCESS)
|
||||
return AES_FAILURE ;
|
||||
xor_block (plain, iv) ;
|
||||
copy_n_bytes (iv, tmp, N_BLOCK) ;
|
||||
plain += N_BLOCK ;
|
||||
cipher += N_BLOCK;
|
||||
}
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void AES::set_IV(unsigned long long int IVCl){
|
||||
memcpy(iv,&IVCl,8);
|
||||
memcpy(iv+8,&IVCl,8);
|
||||
IVC = IVCl;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::iv_inc(){
|
||||
IVC += 1;
|
||||
memcpy(iv,&IVC,8);
|
||||
memcpy(iv+8,&IVC,8);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int AES::get_size(){
|
||||
return size;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::set_size(int sizel){
|
||||
size = sizel;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::get_IV(byte *out){
|
||||
memcpy(out,&IVC,8);
|
||||
memcpy(out+8,&IVC,8);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::calc_size_n_pad(int p_size){
|
||||
int s_of_p = p_size - 1;
|
||||
if ( s_of_p % N_BLOCK == 0){
|
||||
size = s_of_p;
|
||||
}else{
|
||||
size = s_of_p + (N_BLOCK-(s_of_p % N_BLOCK));
|
||||
}
|
||||
pad = size - s_of_p;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::padPlaintext(void* in,byte* out)
|
||||
{
|
||||
memcpy(out,in,size);
|
||||
for (int i = size-pad; i < size; i++){;
|
||||
out[i] = arr_pad[pad - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool AES::CheckPad(byte* in,int lsize){
|
||||
if (in[lsize-1] <= 0x0f){
|
||||
int lpad = (int)in[lsize-1];
|
||||
for (int i = lsize - 1; i >= lsize-lpad; i--){
|
||||
if (arr_pad[lpad - 1] != in[i]){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::printArray(byte output[],bool p_pad)
|
||||
{
|
||||
uint8_t i,j;
|
||||
uint8_t loops = size/N_BLOCK;
|
||||
uint8_t outp = N_BLOCK;
|
||||
for (j = 0; j < loops; j += 1){
|
||||
if (p_pad && (j == (loops - 1)) ) { outp = N_BLOCK - pad; }
|
||||
for (i = 0; i < outp; i++)
|
||||
{
|
||||
printf_P(PSTR("%c"),output[j*N_BLOCK + i]);
|
||||
}
|
||||
}
|
||||
printf_P(PSTR("\n"));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::printArray(byte output[],int sizel)
|
||||
{
|
||||
for (int i = 0; i < sizel; i++)
|
||||
{
|
||||
printf_P(PSTR("%x"),output[i]);
|
||||
}
|
||||
printf_P(PSTR("\n"));
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]){
|
||||
calc_size_n_pad(size_p);
|
||||
byte plain_p[get_size()];
|
||||
padPlaintext(plain,plain_p);
|
||||
int blocks = get_size() / N_BLOCK;
|
||||
set_key (key, bits) ;
|
||||
cbc_encrypt (plain_p, cipher, blocks, ivl);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){
|
||||
calc_size_n_pad(size_p);
|
||||
byte plain_p[get_size()];
|
||||
padPlaintext(plain,plain_p);
|
||||
int blocks = get_size() / N_BLOCK;
|
||||
set_key (key, bits) ;
|
||||
cbc_encrypt (plain_p, cipher, blocks);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]){
|
||||
set_size(size_c);
|
||||
int blocks = size_c / N_BLOCK;
|
||||
set_key (key, bits);
|
||||
cbc_decrypt (cipher,plain, blocks, ivl);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits){
|
||||
set_size(size_c);
|
||||
int blocks = size_c / N_BLOCK;
|
||||
set_key (key, bits);
|
||||
cbc_decrypt (cipher,plain, blocks);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#if defined(AES_LINUX)
|
||||
double AES::millis(){
|
||||
gettimeofday(&tv, NULL);
|
||||
return (tv.tv_sec + 0.000001 * tv.tv_usec);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,415 @@
|
||||
#ifndef __AES_H__
|
||||
#define __AES_H__
|
||||
|
||||
#include "AES_config.h"
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
1. source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
2. binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation;
|
||||
|
||||
3. the name of the copyright holder is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue 09/09/2006
|
||||
|
||||
This is an AES implementation that uses only 8-bit byte operations on the
|
||||
cipher state.
|
||||
*/
|
||||
|
||||
/* code was modified by george spanos <spaniakos@gmail.com>
|
||||
* 16/12/14
|
||||
*/
|
||||
|
||||
class AES
|
||||
{
|
||||
public:
|
||||
|
||||
/* The following calls are for a precomputed key schedule
|
||||
|
||||
NOTE: If the length_type used for the key length is an
|
||||
unsigned 8-bit character, a key length of 256 bits must
|
||||
be entered as a length in bytes (valid inputs are hence
|
||||
128, 192, 16, 24 and 32).
|
||||
*/
|
||||
/** \fn AES()
|
||||
* \brief AES constructor
|
||||
*
|
||||
* This function initialized an instance of AES.
|
||||
*/
|
||||
AES();
|
||||
|
||||
/** Set the cipher key for the pre-keyed version.
|
||||
* @param key[] pointer to the key string.
|
||||
* @param keylen Integer that indicates the length of the key.
|
||||
* @note NOTE: If the length_type used for the key length is an unsigned 8-bit character,
|
||||
* a key length of 256 bits must be entered as a length in bytes
|
||||
* (valid inputs are hence 128, 192, 16, 24 and 32).
|
||||
*
|
||||
*/
|
||||
byte set_key (byte key[], int keylen) ;
|
||||
|
||||
/** clean up subkeys after use.
|
||||
*
|
||||
*/
|
||||
void clean () ; // delete key schedule after use
|
||||
|
||||
/** copying and xoring utilities.
|
||||
* @param *AESt byte pointer of the AEStination array.
|
||||
* @param *src byte pointer of the source array.
|
||||
* @param n byte, indicating the sizeof the bytes to be copied.
|
||||
* @note this is an alternative for memcpy(void *s1,const void *s2, site_t n),
|
||||
* i have not updated the function in the implementation yet, but it is considered a future plan.
|
||||
*
|
||||
*/
|
||||
void copy_n_bytes (byte * AESt, byte * src, byte n) ;
|
||||
|
||||
/** Encrypt a single block of 16 bytes .
|
||||
* @param plain[N_BLOCK] Array of the plaintext.
|
||||
* @param cipher[N_BLOCK] Array of the ciphertext.
|
||||
* @note The N_BLOCK is defined in AES_config.h as,
|
||||
* @code #define N_ROW 4
|
||||
* #define N_COL 4
|
||||
* #define N_BLOCK (N_ROW * N_COL)
|
||||
* @endcode
|
||||
* Changed to that will change the Block_size.
|
||||
* @Return 0 if SUCCESS or -1 if FAILURE
|
||||
*
|
||||
*/
|
||||
byte encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) ;
|
||||
|
||||
/** CBC encrypt a number of blocks (input and return an IV).
|
||||
*
|
||||
* @param *plain Pointer, points to the plaintex.
|
||||
* @param *cipher Pointer, points to the ciphertext that will be created.
|
||||
* @param n_block integer, indicated the number of blocks to be ciphered.
|
||||
* @param iv[N_BLOCK] byte Array that holds the IV (initialization vector).
|
||||
* @Return 0 if SUCCESS or -1 if FAILURE
|
||||
*
|
||||
*/
|
||||
byte cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) ;
|
||||
|
||||
/** CBC encrypt a number of blocks (input and return an IV).
|
||||
*
|
||||
* @param *plain Pointer, points to the plaintex.
|
||||
* @param *cipher Pointer, points to the ciphertext that will be created.
|
||||
* @param n_block integer, indicated the number of blocks to be ciphered.
|
||||
* @Return 0 if SUCCESS or -1 if FAILURE
|
||||
*
|
||||
*/
|
||||
byte cbc_encrypt (byte * plain, byte * cipher, int n_block) ;
|
||||
|
||||
|
||||
/** Decrypt a single block of 16 bytes
|
||||
* @param cipher[N_BLOCK] Array of the ciphertext.
|
||||
* @param plain[N_BLOCK] Array of the plaintext.
|
||||
* @note The N_BLOCK is defined in AES_config.h as,
|
||||
* @code #define N_ROW 4
|
||||
* #define N_COL 4
|
||||
* #define N_BLOCK (N_ROW * N_COL)
|
||||
* @endcode
|
||||
* Changed to that will change the Block_size.
|
||||
* @Return 0 if SUCCESS or -1 if FAILURE
|
||||
*
|
||||
*/
|
||||
byte decrypt (byte cipher [N_BLOCK], byte plain [N_BLOCK]) ;
|
||||
|
||||
/** CBC decrypt a number of blocks (input and return an IV)
|
||||
*
|
||||
* @param *cipher Pointer, points to the ciphertext that will be created.
|
||||
* @param *plain Pointer, points to the plaintex.
|
||||
* @param n_block integer, indicated the number of blocks to be ciphered.
|
||||
* @param iv[N_BLOCK] byte Array that holds the IV (initialization vector).
|
||||
* @Return 0 if SUCCESS or -1 if FAILURE
|
||||
*
|
||||
*/
|
||||
byte cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) ;
|
||||
|
||||
/** CBC decrypt a number of blocks (input and return an IV)
|
||||
*
|
||||
* @param *cipher Pointer, points to the ciphertext that will be created.
|
||||
* @param *plain Pointer, points to the plaintex.
|
||||
* @param n_block integer, indicated the number of blocks to be ciphered.
|
||||
* @Return 0 if SUCCESS or -1 if FAILURE
|
||||
*
|
||||
*/
|
||||
byte cbc_decrypt (byte * cipher, byte * plain, int n_block) ;
|
||||
|
||||
/** Sets IV (initialization vector) and IVC (IV counter).
|
||||
* This function changes the ivc and iv variables needed for AES.
|
||||
*
|
||||
* @param IVCl int or hex value of iv , ex. 0x0000000000000001
|
||||
* @note example:
|
||||
* @code unsigned long long int my_iv = 01234567; @endcode
|
||||
*/
|
||||
void set_IV(unsigned long long int IVCl);
|
||||
|
||||
/** increase the iv (initialization vector) and IVC (IV counter) by 1
|
||||
*
|
||||
* This function increased the VI by one step in order to have a different IV each time
|
||||
*
|
||||
*/
|
||||
void iv_inc();
|
||||
|
||||
/** Getter method for size
|
||||
*
|
||||
* This function return the size
|
||||
* @return an integer, that is the size of the of the padded plaintext,
|
||||
* thus, the size of the ciphertext.
|
||||
*/
|
||||
int get_size();
|
||||
|
||||
/** Setter method for size
|
||||
*
|
||||
* This function sets the size of the plaintext+pad
|
||||
*
|
||||
*/
|
||||
void set_size(int sizel);
|
||||
|
||||
/** Getter method for IV
|
||||
*
|
||||
* This function return the IV
|
||||
* @param out byte pointer that gets the IV.
|
||||
* @return none, the IV is writed to the out pointer.
|
||||
*/
|
||||
void get_IV(byte *out);
|
||||
|
||||
/** Calculates the size of the plaintext and the padding.
|
||||
*
|
||||
* Calculates the size of theplaintext with the padding
|
||||
* and the size of the padding needed. Moreover it stores them in their class variables.
|
||||
*
|
||||
* @param p_size the size of the byte array ex sizeof(plaintext)
|
||||
*/
|
||||
void calc_size_n_pad(int p_size);
|
||||
|
||||
/** Pads the plaintext
|
||||
*
|
||||
* This function pads the plaintext and returns an char array with the
|
||||
* plaintext and the padding in order for the plaintext to be compatible with
|
||||
* 16bit size blocks required by AES
|
||||
*
|
||||
* @param in the string of the plaintext in a byte array
|
||||
* @param out The string of the out array.
|
||||
* @return no return, The padded plaintext is stored in the out pointer.
|
||||
*/
|
||||
void padPlaintext(void* in,byte* out);
|
||||
|
||||
/** Check the if the padding is correct.
|
||||
*
|
||||
* This functions checks the padding of the plaintext.
|
||||
*
|
||||
* @param in the string of the plaintext in a byte array
|
||||
* @param size the size of the string
|
||||
* @return true if correct / false if not
|
||||
*/
|
||||
bool CheckPad(byte* in,int size);
|
||||
|
||||
/** Prints the array given.
|
||||
*
|
||||
* This function prints the given array and pad,
|
||||
* It is mainlly used for debugging purpuses or to output the string.
|
||||
*
|
||||
* @param output[] the string of the text in a byte array
|
||||
* @param p_pad optional, used to print with out the padding characters
|
||||
*/
|
||||
void printArray(byte output[],bool p_pad = true);
|
||||
|
||||
/** Prints the array given.
|
||||
*
|
||||
* This function prints the given array in Hexadecimal.
|
||||
*
|
||||
* @param output[] the string of the text in a byte array
|
||||
* @param sizel the size of the array.
|
||||
*/
|
||||
void printArray(byte output[],int sizel);
|
||||
|
||||
/** User friendly implementation of AES-CBC encryption.
|
||||
*
|
||||
* @param *plain pointer to the plaintext
|
||||
* @param size_p size of the plaintext
|
||||
* @param *cipher pointer to the ciphertext
|
||||
* @param *key pointer to the key that will be used.
|
||||
* @param bits bits of the encryption/decrpytion
|
||||
* @param ivl[N_BLOCK] the initialization vector IV that will be used for encryption.
|
||||
* @note The key will be stored in class variable.
|
||||
*/
|
||||
void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]);
|
||||
|
||||
/** User friendly implementation of AES-CBC encryption.
|
||||
*
|
||||
* @param *plain pointer to the plaintext
|
||||
* @param size_p size of the plaintext
|
||||
* @param *cipher pointer to the ciphertext
|
||||
* @param *key pointer to the key that will be used.
|
||||
* @param bits bits of the encryption/decrpytion
|
||||
* @note The key will be stored in class variable.
|
||||
*/
|
||||
void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits);
|
||||
|
||||
/** User friendly implementation of AES-CBC decryption.
|
||||
*
|
||||
* @param *cipher pointer to the ciphertext
|
||||
* @param size_c size of the ciphertext
|
||||
* @param *plain pointer to the plaintext
|
||||
* @param *key pointer to the key that will be used.
|
||||
* @param bits bits of the encryption/decrpytion
|
||||
* @param ivl[N_BLOCK] the initialization vector IV that will be used for decryption.
|
||||
* @note The key will be stored in class variable.
|
||||
*/
|
||||
void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]);
|
||||
|
||||
/** User friendly implementation of AES-CBC decryption.
|
||||
*
|
||||
* @param *cipher pointer to the ciphertext
|
||||
* @param size_c size of the ciphertext
|
||||
* @param *plain pointer to the plaintext
|
||||
* @param *key pointer to the key that will be used.
|
||||
* @param bits bits of the encryption/decrpytion
|
||||
* @note The key will be stored in class variable.
|
||||
*/
|
||||
void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits);
|
||||
|
||||
#if defined(AES_LINUX)
|
||||
/**
|
||||
* used in linux in order to retrieve the time in milliseconds.
|
||||
*
|
||||
* @return returns the milliseconds in a double format.
|
||||
*/
|
||||
double millis();
|
||||
#endif
|
||||
private:
|
||||
int round ;/**< holds the number of rounds to be used. */
|
||||
byte key_sched [KEY_SCHEDULE_BYTES] ;/**< holds the pre-computed key for the encryption/decrpytion. */
|
||||
unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */
|
||||
byte iv[16];/**< holds the initialization vector that will be used in the cipher. */
|
||||
int pad;/**< holds the size of the padding. */
|
||||
int size;/**< hold the size of the plaintext to be ciphered */
|
||||
#if defined(AES_LINUX)
|
||||
timeval tv;/**< holds the time value on linux */
|
||||
byte arr_pad[15];/**< holds the hexadecimal padding values on linux */
|
||||
#else
|
||||
byte arr_pad[15];// = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };/**< holds the hexadecimal padding values */
|
||||
#endif
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @example aes.ino
|
||||
* <b>For Arduino</b><br>
|
||||
* <b>Updated: spaniakos 2015 </b><br>
|
||||
*
|
||||
* This is an example of how to use AES in CBC mode easily.
|
||||
* The text and keys can be either in HEX or String format.<br />
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example aes.cpp
|
||||
* <b>For Rasberry pi</b><br>
|
||||
* <b>Updated: spaniakos 2015 </b><br>
|
||||
*
|
||||
* This is an example of how to use AES in CBC mode easily.
|
||||
* The text and keys can be either in HEX or String format.<br />
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example test_vectors.ino
|
||||
* <b>For Arduino</b><br>
|
||||
* <b>Updated: spaniakos 2015 </b><br>
|
||||
*
|
||||
* This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br />
|
||||
* plus is a classical approach to the AES encryption library with out the easy to use add-on modifications.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example test_vectors.cpp
|
||||
* <b>For Rasberry pi</b><br>
|
||||
* <b>Updated: spaniakos 2015 </b><br>
|
||||
*
|
||||
* This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br />
|
||||
* plus is a classical approach to the AES encryption library with out the easy to use add-on modifications.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage AES library for Arduino and Raspberry pi.
|
||||
*
|
||||
* @section Goals design Goals
|
||||
*
|
||||
* This library is AESigned to be...
|
||||
* @li Fast and efficient.
|
||||
* @li Able to effectively encrypt and decrypt any size of string.
|
||||
* @li Able to encrypt and decrypt using AES
|
||||
* @li Able to encrypt and decrypt using AES-CBC
|
||||
* @li Easy for the user to use in his programs.
|
||||
*
|
||||
* @section Acknowledgements Acknowledgements
|
||||
* This is an AES library for the Arduino, based on tzikis's AES library, which you can find <a href= "https://github.com/tzikis/arduino">here:</a>.<br />
|
||||
* Tzikis library was based on scottmac`s library, which you can find <a href="https://github.com/scottmac/arduino">here:</a><br />
|
||||
*
|
||||
* @section Installation Installation
|
||||
* <h3>Arduino</h3>
|
||||
* Create a folder named _AES_ in the _libraries_ folder inside your Arduino sketch folder. If the
|
||||
* libraries folder doesn't exist, create it. Then copy everything inside. (re)launch the Arduino IDE.<br />
|
||||
* You're done. Time for a mojito
|
||||
*
|
||||
* <h3>Raspberry pi</h3>
|
||||
* <b>install</b><br /><br />
|
||||
*
|
||||
* sudo make install<br />
|
||||
* cd examples_Rpi<br />
|
||||
* make<br /><br />
|
||||
*
|
||||
* <b>What to do after changes to the library</b><br /><br />
|
||||
* sudo make clean<br />
|
||||
* sudo make install<br />
|
||||
* cd examples_Rpi<br />
|
||||
* make clean<br />
|
||||
* make<br /><br />
|
||||
* <b>What to do after changes to a sketch</b><br /><br />
|
||||
* cd examples_Rpi<br />
|
||||
* make <sketch><br /><br />
|
||||
* or <br />
|
||||
* make clean<br />
|
||||
* make<br /><br /><br />
|
||||
* <b>How to start a sketch</b><br /><br />
|
||||
* cd examples_Rpi<br />
|
||||
* sudo ./<sketch><br /><br />
|
||||
*
|
||||
* @section News News
|
||||
*
|
||||
* If issues are discovered with the documentation, please report them <a href="https://github.com/spaniakos/spaniakos.github.io/issues"> here</a>
|
||||
* @section Useful Useful References
|
||||
*
|
||||
* Please refer to:
|
||||
*
|
||||
* @li <a href="http://spaniakos.github.io/AES/classAES.html"><b>AES</b> Class Documentation</a>
|
||||
* @li <a href="https://github.com/spaniakos/AES/archive/master.zip"><b>Download</b></a>
|
||||
* @li <a href="https://github.com/spaniakos/AES/"><b>Source Code</b></a>
|
||||
* @li <a href="http://spaniakos.github.io/">All spaniakos Documentation Main Page</a>
|
||||
*
|
||||
* @section Board_Support Board Support
|
||||
*
|
||||
* Most standard Arduino based boards are supported:
|
||||
* - Arduino
|
||||
* - Intel Galileo support
|
||||
* - Raspberry Pi Support
|
||||
*
|
||||
* - The library has not been tested to other boards, but it should suppport ATMega 328 based boards,Mega Boards,Arduino Due,ATTiny board
|
||||
*/
|
||||
@@ -0,0 +1,44 @@
|
||||
/* code was modified by george spanos <spaniakos@gmail.com>
|
||||
* 16/12/14
|
||||
*/
|
||||
|
||||
#ifndef __AES_CONFIG_H__
|
||||
#define __AES_CONFIG_H__
|
||||
|
||||
#if (defined(__linux) || defined(linux)) && !defined(__ARDUINO_X86__)
|
||||
|
||||
#define AES_LINUX
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__ARDUINO_X86__) || (defined (__linux) || defined (linux))
|
||||
#undef PROGMEM
|
||||
#define PROGMEM __attribute__(( section(".progmem.data") ))
|
||||
#define pgm_read_byte(p) (*(p))
|
||||
typedef unsigned char byte;
|
||||
#define printf_P printf
|
||||
#define PSTR(x) (x)
|
||||
#else
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
||||
#define N_ROW 4
|
||||
#define N_COL 4
|
||||
#define N_BLOCK (N_ROW * N_COL)
|
||||
#define N_MAX_ROUNDS 14
|
||||
#define KEY_SCHEDULE_BYTES ((N_MAX_ROUNDS + 1) * N_BLOCK)
|
||||
#define AES_SUCCESS (0)
|
||||
#define AES_FAILURE (-1)
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
#############################################################################
|
||||
#
|
||||
# Makefile for AES on Raspberry Pi
|
||||
#
|
||||
# License: GPL (General Public License)
|
||||
# Author: Georgios Spanos (spaniakos) <spaniakos@gmail.com>
|
||||
# Date: 02/12/2014
|
||||
#
|
||||
# Description:
|
||||
# ------------
|
||||
# use make all and mak install to install the library
|
||||
# You can change the install directory by editing the LIBDIR line
|
||||
#
|
||||
PREFIX=/usr/local
|
||||
|
||||
# Library parameters
|
||||
# where to put the lib
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
# lib name
|
||||
LIB=libAES
|
||||
# shared library name
|
||||
LIBNAME=$(LIB).so.1.0
|
||||
|
||||
# Where to put the header files
|
||||
HEADER_DIR=${PREFIX}/include/AES
|
||||
|
||||
# The recommended compiler flags for the Raspberry Pi
|
||||
CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
|
||||
|
||||
# make all
|
||||
# reinstall the library after each recompilation
|
||||
all: libAES
|
||||
|
||||
# Make the library
|
||||
libAES: AES.o
|
||||
g++ -shared -Wl,-soname,$@.so.1 ${CCFLAGS} -o ${LIBNAME} $^
|
||||
|
||||
# Library parts
|
||||
AES.o: AES.cpp
|
||||
g++ -Wall -fPIC ${CCFLAGS} -c $^
|
||||
|
||||
# clear build files
|
||||
clean:
|
||||
rm -rf *.o ${LIB}.*
|
||||
rm -rf ${LIBDIR}/${LIB}.*
|
||||
rm -rf ${HEADER_DIR}
|
||||
|
||||
install: all install-libs install-headers
|
||||
|
||||
# Install the library to LIBPATH
|
||||
install-libs:
|
||||
@echo "[Installing Libs]"
|
||||
@if ( test ! -d $(PREFIX)/lib ) ; then mkdir -p $(PREFIX)/lib ; fi
|
||||
@install -m 0755 ${LIBNAME} ${LIBDIR}
|
||||
@ln -sf ${LIBDIR}/${LIBNAME} ${LIBDIR}/${LIB}.so.1
|
||||
@ln -sf ${LIBDIR}/${LIBNAME} ${LIBDIR}/${LIB}.so
|
||||
@ldconfig
|
||||
|
||||
install-headers:
|
||||
@echo "[Installing Headers]"
|
||||
@if ( test ! -d ${HEADER_DIR} ) ; then mkdir -p ${HEADER_DIR} ; fi
|
||||
@install -m 0644 *.h ${HEADER_DIR}
|
||||
@@ -0,0 +1,91 @@
|
||||
### Arduino
|
||||
just run the sketched aftel loading the libraries.
|
||||
|
||||
### Raspberry pi
|
||||
install
|
||||
```
|
||||
sudo make install
|
||||
cd examples_Rpi
|
||||
make
|
||||
```
|
||||
|
||||
What to do after changes to the library
|
||||
```
|
||||
sudo make clean
|
||||
sudo make install
|
||||
cd examples_Rpi
|
||||
make clean
|
||||
make
|
||||
```
|
||||
|
||||
What to do after changes to a sketch
|
||||
```
|
||||
cd examples_Rpi
|
||||
make <sketch>
|
||||
|
||||
or
|
||||
make clean
|
||||
make
|
||||
```
|
||||
|
||||
How to start a sketch
|
||||
```
|
||||
cd examples_Rpi
|
||||
sudo ./<sketch>
|
||||
```
|
||||
|
||||
This is a derived work from Brian Gladman's AES implementation for byte-oriented
|
||||
processors, here's the licence terms:
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
1. source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
2. binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation;
|
||||
|
||||
3. the name of the copyright holder is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue 09/09/2006
|
||||
|
||||
This is an AES implementation that uses only 8-bit byte operations on the
|
||||
cipher state (there are options to use 32-bit types if available).
|
||||
|
||||
The combination of mix columns and byte substitution used here is based on
|
||||
that developed by Karl Malbrain. His contribution is acknowledged.
|
||||
*/
|
||||
|
||||
/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down
|
||||
and tailored to 8-bit microcontroller abilities and Arduino datatypes.
|
||||
|
||||
The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all
|
||||
the other transformations are coded to save table space. Many efficiency
|
||||
improvments to the routines mix_sub_columns() and inv_mix_sub_columns()
|
||||
(mainly common sub-expression elimination).
|
||||
|
||||
Only the routines with precalculated subkey schedule are retained (together
|
||||
with set_key() - this does however mean each AES object takes 240 bytes of
|
||||
RAM, alas)
|
||||
|
||||
The CBC routines side-effect the iv argument (so that successive calls work
|
||||
together correctly).
|
||||
|
||||
All the encryption and decryption routines work with plain == cipher for
|
||||
in-place encryption, note.
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <AES.h>
|
||||
#include "./printf.h"
|
||||
|
||||
AES aes ;
|
||||
|
||||
byte *key = (unsigned char*)"0123456789010123";
|
||||
|
||||
byte plain[] = "Add NodeAdd NodeAdd NodeAdd NodeAdd Node";
|
||||
|
||||
//real iv = iv x2 ex: 01234567 = 0123456701234567
|
||||
unsigned long long int my_iv = 36753562;
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (57600) ;
|
||||
printf_begin();
|
||||
delay(500);
|
||||
printf("\n===testng mode\n") ;
|
||||
|
||||
// otfly_test () ;
|
||||
// otfly_test256 () ;
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
prekey_test () ;
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void prekey (int bits)
|
||||
{
|
||||
aes.iv_inc();
|
||||
byte iv [N_BLOCK] ;
|
||||
byte plain_p[48];
|
||||
byte cipher [48] ;
|
||||
byte check [48] ;
|
||||
unsigned long ms = micros ();
|
||||
aes.set_IV(my_iv);
|
||||
aes.get_IV(iv);
|
||||
aes.do_aes_encrypt(plain,41,cipher,key,bits,iv);
|
||||
Serial.print("Encryption took: ");
|
||||
Serial.println(micros() - ms);
|
||||
ms = micros ();
|
||||
aes.set_IV(my_iv);
|
||||
aes.get_IV(iv);
|
||||
aes.do_aes_decrypt(cipher,48,check,key,bits,iv);
|
||||
Serial.print("Decryption took: ");
|
||||
Serial.println(micros() - ms);
|
||||
printf("\n\nPLAIN :");
|
||||
aes.printArray(plain,(bool)true);
|
||||
printf("\nCIPHER:");
|
||||
aes.printArray(cipher,(bool)false);
|
||||
printf("\nCHECK :");
|
||||
aes.printArray(check,(bool)true);
|
||||
printf("\nIV :");
|
||||
aes.printArray(iv,16);
|
||||
printf("\n============================================================\n");
|
||||
}
|
||||
|
||||
void prekey_test ()
|
||||
{
|
||||
prekey (128) ;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
Monte Carlo test vectors:
|
||||
http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesmct.zip
|
||||
|
||||
(Compare the Monte Carlo output to the ECBMCT128.rsp file)
|
||||
|
||||
Known Answer Tests:
|
||||
http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
|
||||
|
||||
- Compare the other test outputs to
|
||||
ECBVarTxt128.rsp
|
||||
ECBVarKey128.rsp
|
||||
ECBVarTxt192.rsp
|
||||
ECBVarKey192.rsp
|
||||
ECBVarTxt256.rsp
|
||||
ECBVarKey256.rsp
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,191 @@
|
||||
#include <AES.h>
|
||||
|
||||
AES aes ;
|
||||
|
||||
byte key [2*N_BLOCK] ;
|
||||
byte plain [N_BLOCK] ;
|
||||
byte iv [N_BLOCK] ;
|
||||
byte cipher [N_BLOCK] ;
|
||||
byte check [N_BLOCK] ;
|
||||
|
||||
void loop ()
|
||||
{}
|
||||
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (57600) ;
|
||||
Serial.print ("AES library test vectors") ;
|
||||
|
||||
monte_carlo (128) ;
|
||||
|
||||
for (int keysize = 128 ; keysize <= 256 ; keysize += 64)
|
||||
{
|
||||
prekey_test_var_plaintext (keysize) ;
|
||||
prekey_test_var_key (keysize) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void prekey_test_var_plaintext (int bits)
|
||||
{
|
||||
Serial.println () ;
|
||||
Serial.print ("ECB Varying Plaintext ") ;
|
||||
Serial.print (bits) ;
|
||||
Serial.println (" bits") ;
|
||||
Serial.println () ;
|
||||
|
||||
byte succ ;
|
||||
set_bits (bits, key, 0) ; // all zero key
|
||||
succ = aes.set_key (key, bits) ;
|
||||
if (succ != SUCCESS)
|
||||
Serial.println ("Failure set_key") ;
|
||||
|
||||
|
||||
for (int bitcount = 1 ; bitcount <= 128 ; bitcount++)
|
||||
{
|
||||
Serial.print ("COUNT = ") ; Serial.println (bitcount-1) ;
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
set_bits (128, plain, bitcount) ;
|
||||
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
if (succ != SUCCESS)
|
||||
Serial.println ("Failure encrypt") ;
|
||||
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
|
||||
succ = aes.decrypt (cipher, check) ;
|
||||
if (succ != SUCCESS)
|
||||
Serial.println ("Failure decrypt") ;
|
||||
|
||||
//print_value ("CHECK = ", check, 128) ;
|
||||
check_same (plain, check, 128) ;
|
||||
Serial.println () ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void prekey_test_var_key (int bits)
|
||||
{
|
||||
Serial.println () ;
|
||||
Serial.print ("ECB Varying Key ") ;
|
||||
Serial.print (bits) ;
|
||||
Serial.println (" bits") ;
|
||||
Serial.println () ;
|
||||
|
||||
byte succ ;
|
||||
set_bits (128, plain, 0) ;
|
||||
|
||||
for (int bitcount = 1 ; bitcount <= bits ; bitcount++)
|
||||
{
|
||||
set_bits (bits, key, bitcount) ; // all zero key
|
||||
succ = aes.set_key (key, bits) ;
|
||||
if (succ != SUCCESS)
|
||||
Serial.println ("Failure set_key") ;
|
||||
Serial.print ("COUNT = ") ; Serial.println (bitcount-1) ;
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
if (succ != SUCCESS)
|
||||
Serial.println ("Failure encrypt") ;
|
||||
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
|
||||
succ = aes.decrypt (cipher, check) ;
|
||||
if (succ != SUCCESS)
|
||||
Serial.println ("Failure decrypt") ;
|
||||
|
||||
check_same (plain, check, 128) ;
|
||||
Serial.println () ;
|
||||
}
|
||||
}
|
||||
|
||||
void set_bits (int bits, byte * a, int count)
|
||||
{
|
||||
bits >>= 3 ;
|
||||
byte bcount = count >> 3 ;
|
||||
for (byte i = 0 ; i < bcount ; i++)
|
||||
a [i] = 0xFF ;
|
||||
if ((count & 7) != 0)
|
||||
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
|
||||
for (byte i = bcount ; i < bits ; i++)
|
||||
a [i] = 0x00 ;
|
||||
}
|
||||
|
||||
void check_same (byte * a, byte * b, int bits)
|
||||
{
|
||||
bits >>= 3 ;
|
||||
for (byte i = 0 ; i < bits ; i++)
|
||||
if (a[i] != b[i])
|
||||
{
|
||||
Serial.println ("Failure plain != check") ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
char hex[] = "0123456789abcdef" ;
|
||||
|
||||
|
||||
void print_value (const char * str, byte * a, int bits)
|
||||
{
|
||||
Serial.print (str) ;
|
||||
bits >>= 3 ;
|
||||
for (int i = 0 ; i < bits ; i++)
|
||||
{
|
||||
byte b = a[i] ;
|
||||
Serial.print (hex [b >> 4]) ;
|
||||
Serial.print (hex [b & 15]) ;
|
||||
}
|
||||
Serial.println () ;
|
||||
}
|
||||
|
||||
byte monteplain [] =
|
||||
{ 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
|
||||
0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ;
|
||||
byte montekey [] =
|
||||
{ 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
|
||||
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ;
|
||||
|
||||
void monte_carlo (int bits)
|
||||
{
|
||||
Serial.println () ;
|
||||
Serial.print ("Monte Carlo ") ;
|
||||
Serial.print (bits) ;
|
||||
Serial.println (" bits") ;
|
||||
Serial.println () ;
|
||||
byte succ ;
|
||||
for (int i = 0 ; i < 16 ; i++)
|
||||
{
|
||||
plain [i] = monteplain [i] ;
|
||||
key [i] = montekey [i] ;
|
||||
}
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
Serial.print ("COUNT = ") ; Serial.println (i) ;
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
succ = aes.set_key (key, bits) ;
|
||||
for (int j = 0 ; j < 1000 ; j++)
|
||||
{
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
aes.copy_n_bytes (plain, cipher, 16) ;
|
||||
}
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
Serial.println () ;
|
||||
if (bits == 128)
|
||||
{
|
||||
for (byte k = 0 ; k < 16 ; k++)
|
||||
key [k] ^= cipher [k] ;
|
||||
}
|
||||
else if (bits == 192)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#############################################################################
|
||||
#
|
||||
# Makefile for AES examples on Raspberry Pi
|
||||
#
|
||||
# License: GPL (General Public License)
|
||||
# Author: gnulnulf <arco@appeltaart.mine.nu>
|
||||
# Date: 2013/02/07 (version 1.0)
|
||||
#
|
||||
# Description:
|
||||
# ------------
|
||||
# use make all and make install to install the examples
|
||||
# You can change the install directory by editing the prefix line
|
||||
#
|
||||
prefix := /usr/local
|
||||
|
||||
# The recommended compiler flags for the Raspberry Pi
|
||||
CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
|
||||
#CCFLAGS=
|
||||
|
||||
# define all programs
|
||||
PROGRAMS = aes test_vectors
|
||||
SOURCES = ${PROGRAMS:=.cpp}
|
||||
|
||||
all: ${PROGRAMS}
|
||||
|
||||
${PROGRAMS}: ${SOURCES}
|
||||
g++ ${CCFLAGS} -Wall -I../ -lAES $@.cpp -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(PROGRAMS)
|
||||
|
||||
install: all
|
||||
test -d $(prefix) || mkdir $(prefix)
|
||||
test -d $(prefix)/bin || mkdir $(prefix)/bin
|
||||
for prog in $(PROGRAMS); do \
|
||||
install -m 0755 $$prog $(prefix)/bin; \
|
||||
done
|
||||
|
||||
.PHONY: install
|
||||
@@ -0,0 +1,16 @@
|
||||
Monte Carlo test vectors:
|
||||
http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesmct.zip
|
||||
|
||||
(Compare the Monte Carlo output to the ECBMCT128.rsp file)
|
||||
|
||||
Known Answer Tests:
|
||||
http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
|
||||
|
||||
- Compare the other test outputs to
|
||||
ECBVarTxt128.rsp
|
||||
ECBVarKey128.rsp
|
||||
ECBVarTxt192.rsp
|
||||
ECBVarKey192.rsp
|
||||
ECBVarTxt256.rsp
|
||||
ECBVarKey256.rsp
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#include <AES.h>
|
||||
#include "printf.h"
|
||||
|
||||
AES aes;
|
||||
|
||||
void prekey_test ();
|
||||
void prekey (int bits, int blocks);
|
||||
|
||||
byte key[] = "01234567899876543210012345678998";
|
||||
|
||||
byte plain[] = "TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST";
|
||||
|
||||
//real iv = iv x2 ex: 01234567 = 0123456701234567
|
||||
unsigned long long int my_iv = 01234567;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
printf("\n===testng mode\n") ;
|
||||
|
||||
for (int i=0;i<1;i++){
|
||||
prekey_test () ;
|
||||
}
|
||||
}
|
||||
|
||||
void prekey (int bits)
|
||||
{
|
||||
byte iv [N_BLOCK] ;
|
||||
byte plain_p[sizeof(plain) + (N_BLOCK - (sizeof(plain) % 16)) - 1];
|
||||
byte cipher[sizeof(plain_p)];
|
||||
aes.do_aes_encrypt(plain,sizeof(plain),cipher,key,bits);
|
||||
aes.get_IV(iv);
|
||||
aes.do_aes_dencrypt(cipher,aes.get_size(),plain_p,key,bits,iv);
|
||||
//normally u have sizeof(cipher) but if its in the same sketch you cannot determin it dynamically
|
||||
|
||||
printf("\n\nPLAIN :");
|
||||
aes.printArray(plain);
|
||||
printf("\nCIPHER:");
|
||||
aes.printArray(cipher);
|
||||
printf("\nPlain2:");
|
||||
aes.printArray(plain_p);
|
||||
printf("\n============================================================\n");
|
||||
}
|
||||
|
||||
void prekey_test ()
|
||||
{
|
||||
prekey (128) ;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,183 @@
|
||||
#include <AES.h>
|
||||
#include "printf.h"
|
||||
|
||||
AES aes ;
|
||||
|
||||
byte key [2*N_BLOCK] ;
|
||||
byte plain [N_BLOCK] ;
|
||||
byte iv [N_BLOCK] ;
|
||||
byte cipher [N_BLOCK] ;
|
||||
byte check [N_BLOCK] ;
|
||||
|
||||
void print_value (const char * str, byte * a, int bits);
|
||||
void prekey_test_var_plaintext (int bits);
|
||||
void prekey_test_var_key (int bits);
|
||||
void set_bits (int bits, byte * a, int count);
|
||||
void check_same (byte * a, byte * b, int bits);
|
||||
void monte_carlo (int bits);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
printf ("AES library test vectors") ;
|
||||
|
||||
monte_carlo (128) ;
|
||||
|
||||
for (int keysize = 128 ; keysize <= 256 ; keysize += 64)
|
||||
{
|
||||
prekey_test_var_plaintext (keysize) ;
|
||||
prekey_test_var_key (keysize) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void prekey_test_var_plaintext (int bits)
|
||||
{
|
||||
printf ("\nECB Varying Plaintext %i bits\n",bits) ;
|
||||
|
||||
byte succ ;
|
||||
set_bits (bits, key, 0) ; // all zero key
|
||||
succ = aes.set_key (key, bits) ;
|
||||
if (succ != SUCCESS)
|
||||
printf("Failure set_key\n") ;
|
||||
|
||||
|
||||
for (int bitcount = 1 ; bitcount <= 128 ; bitcount++)
|
||||
{
|
||||
printf ("COUNT = %i \n",bitcount-1);
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
set_bits (128, plain, bitcount) ;
|
||||
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
if (succ != SUCCESS)
|
||||
printf ("Failure encrypt\n") ;
|
||||
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
|
||||
succ = aes.decrypt (cipher, check) ;
|
||||
if (succ != SUCCESS)
|
||||
printf ("Failure decrypt\n") ;
|
||||
|
||||
//print_value ("CHECK = ", check, 128) ;
|
||||
check_same (plain, check, 128) ;
|
||||
printf ("\n") ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void prekey_test_var_key (int bits)
|
||||
{
|
||||
printf ("\nECB Varying key %i bits\n",bits);
|
||||
|
||||
byte succ ;
|
||||
set_bits (128, plain, 0) ;
|
||||
|
||||
for (int bitcount = 1 ; bitcount <= bits ; bitcount++)
|
||||
{
|
||||
set_bits (bits, key, bitcount) ; // all zero key
|
||||
succ = aes.set_key (key, bits) ;
|
||||
if (succ != SUCCESS)
|
||||
printf ("Failure set_key\n") ;
|
||||
printf ("COUNT = %i\n",bitcount-1);
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
if (succ != SUCCESS)
|
||||
printf ("Failure encrypt\n") ;
|
||||
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
|
||||
succ = aes.decrypt (cipher, check) ;
|
||||
if (succ != SUCCESS)
|
||||
printf ("Failure decrypt\n") ;
|
||||
|
||||
check_same (plain, check, 128) ;
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void set_bits (int bits, byte * a, int count)
|
||||
{
|
||||
bits >>= 3 ;
|
||||
byte bcount = count >> 3 ;
|
||||
for (byte i = 0 ; i < bcount ; i++)
|
||||
a [i] = 0xFF ;
|
||||
if ((count & 7) != 0)
|
||||
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
|
||||
for (byte i = bcount ; i < bits ; i++)
|
||||
a [i] = 0x00 ;
|
||||
}
|
||||
|
||||
void check_same (byte * a, byte * b, int bits)
|
||||
{
|
||||
bits >>= 3 ;
|
||||
for (byte i = 0 ; i < bits ; i++)
|
||||
if (a[i] != b[i])
|
||||
{
|
||||
printf ("Failure plain != check\n") ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
char hex[] = "0123456789abcdef" ;
|
||||
|
||||
|
||||
void print_value (const char * str, byte * a, int bits)
|
||||
{
|
||||
printf ("%s",str) ;
|
||||
bits >>= 3 ;
|
||||
for (int i = 0 ; i < bits ; i++)
|
||||
{
|
||||
byte b = a[i] ;
|
||||
printf("%c%c",hex[b >> 4],hex [b & 15]);
|
||||
//Serial.print (hex [b >> 4]) ;
|
||||
//Serial.print (hex [b & 15]) ;
|
||||
}
|
||||
printf("\n") ;
|
||||
}
|
||||
|
||||
byte monteplain [] =
|
||||
{ 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
|
||||
0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ;
|
||||
byte montekey [] =
|
||||
{ 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
|
||||
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ;
|
||||
|
||||
void monte_carlo (int bits)
|
||||
{
|
||||
printf ("\nMonte Carlo %i bits\n",bits);
|
||||
byte succ;
|
||||
for (int i = 0 ; i < 16 ; i++)
|
||||
{
|
||||
plain [i] = monteplain [i] ;
|
||||
key [i] = montekey [i] ;
|
||||
}
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
printf ("COUNT = %i\n",i);
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
succ = aes.set_key (key, bits) ;
|
||||
for (int j = 0 ; j < 1000 ; j++)
|
||||
{
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
aes.copy_n_bytes (plain, cipher, 16) ;
|
||||
}
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
printf("\n");
|
||||
if (bits == 128)
|
||||
{
|
||||
for (byte k = 0 ; k < 16 ; k++)
|
||||
key [k] ^= cipher [k] ;
|
||||
}
|
||||
else if (bits == 192)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
AES KEYWORD1
|
||||
set_key KEYWORD2
|
||||
clean KEYWORD2
|
||||
encrypt KEYWORD2
|
||||
decrypt KEYWORD2
|
||||
cbc_encrypt KEYWORD2
|
||||
cbc_decrypt KEYWORD2
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
/* Galileo support from spaniakos <spaniakos@gmail.com> */
|
||||
|
||||
/**
|
||||
* @file printf.h
|
||||
*
|
||||
* Setup necessary to direct stdout to the Arduino Serial library, which
|
||||
* enables 'printf'
|
||||
*/
|
||||
|
||||
#ifndef __PRINTF_H__
|
||||
#define __PRINTF_H__
|
||||
|
||||
#if defined (ARDUINO) && !defined (__arm__) && !defined(__ARDUINO_X86__)
|
||||
|
||||
int serial_putc( char c, FILE * )
|
||||
{
|
||||
Serial.write( c );
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void printf_begin(void)
|
||||
{
|
||||
fdevopen( &serial_putc, 0 );
|
||||
}
|
||||
|
||||
#elif defined (__arm__)
|
||||
|
||||
void printf_begin(void){}
|
||||
|
||||
#elif defined(__ARDUINO_X86__)
|
||||
int serial_putc( char c, FILE * )
|
||||
{
|
||||
Serial.write( c );
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void printf_begin(void)
|
||||
{
|
||||
//JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port)
|
||||
stdout = freopen("/dev/ttyGS0","w",stdout);
|
||||
delay(500);
|
||||
printf("redirecting to Serial...");
|
||||
|
||||
//JESUS -----------------------------------------------------------
|
||||
}
|
||||
#else
|
||||
#error This example is only for use on Arduino.
|
||||
#endif // ARDUINO
|
||||
|
||||
#endif // __PRINTF_H__
|
||||
@@ -63,9 +63,11 @@
|
||||
#define MY_RADIO_NRF24
|
||||
//#define MY_RADIO_RFM69
|
||||
|
||||
//#define MY_RF24_ENABLE_ENCRYPTION
|
||||
|
||||
// Enable gateway transportation type
|
||||
#define MY_GATEWAY_W5100
|
||||
//#define MY_GATEWAY_ENC28J60
|
||||
//#define MY_GATEWAY_W5100
|
||||
#define MY_GATEWAY_ENC28J60
|
||||
|
||||
// Enable Soft SPI for radio (note different radio wiring required)
|
||||
// Useful for W5100 which sometimes have hard time co-operate with radio on the same spi bus.
|
||||
|
||||
Reference in New Issue
Block a user