2017-08-18 14:25:14 +08:00
|
|
|
/*
|
|
|
|
* This file is adapted from PolarSSL 1.3.19 (GPL)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "aesni.h"
|
|
|
|
#include "aesarm.h"
|
2017-08-18 22:27:03 +08:00
|
|
|
#include <stdint.h>
|
2017-08-18 14:25:14 +08:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#if defined(AES256) && (AES256 == 1)
|
|
|
|
#define AES_KEYSIZE 256
|
2017-08-18 17:38:24 +08:00
|
|
|
#ifdef HAVE_AMD64
|
2017-08-18 22:27:03 +08:00
|
|
|
#define aeshw_setkey_enc aesni_setkey_enc_256
|
2017-08-18 17:38:24 +08:00
|
|
|
#endif
|
2017-08-18 14:25:14 +08:00
|
|
|
#elif defined(AES192) && (AES192 == 1)
|
|
|
|
#define AES_KEYSIZE 192
|
2017-08-18 17:38:24 +08:00
|
|
|
#ifdef HAVE_AMD64
|
2017-08-18 22:27:03 +08:00
|
|
|
#define aeshw_setkey_enc aesni_setkey_enc_192
|
2017-08-18 17:38:24 +08:00
|
|
|
#endif
|
2017-08-18 14:25:14 +08:00
|
|
|
#else
|
|
|
|
#define AES_KEYSIZE 128
|
2017-08-18 17:38:24 +08:00
|
|
|
#ifdef HAVE_AMD64
|
2017-08-18 22:27:03 +08:00
|
|
|
#define aeshw_setkey_enc aesni_setkey_enc_128
|
2017-08-18 17:38:24 +08:00
|
|
|
#endif
|
2017-08-18 14:25:14 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define AES_NR ((AES_KEYSIZE >> 5) + 6)
|
|
|
|
#define AES_RKSIZE 272
|
|
|
|
|
|
|
|
#ifdef HAVE_AMD64
|
|
|
|
#define HAVE_HARDAES 1
|
2017-08-18 22:27:03 +08:00
|
|
|
#define aeshw_supported aesni_supported
|
|
|
|
#define aeshw_crypt_ecb aesni_crypt_ecb
|
|
|
|
#define aeshw_inverse_key(a,b) aesni_inverse_key(a,b,AES_NR)
|
2017-08-18 14:25:14 +08:00
|
|
|
#endif /* HAVE_AMD64 */
|
|
|
|
|
|
|
|
#ifdef HAVE_ARM64
|
|
|
|
#define HAVE_HARDAES 1
|
2017-08-18 22:27:03 +08:00
|
|
|
#define aeshw_supported aesarm_supported
|
|
|
|
#define aeshw_crypt_ecb aesarm_crypt_ecb
|
2017-08-18 14:25:14 +08:00
|
|
|
|
|
|
|
#include "aesarm_table.h"
|
|
|
|
|
|
|
|
#ifndef GET_UINT32_LE
|
|
|
|
#define GET_UINT32_LE(n,b,i) \
|
|
|
|
{ \
|
|
|
|
(n) = ( (uint32_t) (b)[(i) ] ) \
|
|
|
|
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
|
|
|
|
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
|
|
|
|
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
static void aeshw_setkey_enc(uint8_t *rk, const uint8_t *key)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
uint32_t *RK;
|
|
|
|
|
|
|
|
RK = (uint32_t *) rk;
|
|
|
|
|
|
|
|
for( i = 0; i < ( AES_KEYSIZE >> 5 ); i++ )
|
|
|
|
{
|
|
|
|
GET_UINT32_LE( RK[i], key, i << 2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
switch( AES_NR )
|
|
|
|
{
|
|
|
|
case 10:
|
|
|
|
|
|
|
|
for( i = 0; i < 10; i++, RK += 4 )
|
|
|
|
{
|
|
|
|
RK[4] = RK[0] ^ RCON[i] ^
|
|
|
|
( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
|
|
|
|
|
|
|
|
RK[5] = RK[1] ^ RK[4];
|
|
|
|
RK[6] = RK[2] ^ RK[5];
|
|
|
|
RK[7] = RK[3] ^ RK[6];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 12:
|
|
|
|
|
|
|
|
for( i = 0; i < 8; i++, RK += 6 )
|
|
|
|
{
|
|
|
|
RK[6] = RK[0] ^ RCON[i] ^
|
|
|
|
( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
|
|
|
|
|
|
|
|
RK[7] = RK[1] ^ RK[6];
|
|
|
|
RK[8] = RK[2] ^ RK[7];
|
|
|
|
RK[9] = RK[3] ^ RK[8];
|
|
|
|
RK[10] = RK[4] ^ RK[9];
|
|
|
|
RK[11] = RK[5] ^ RK[10];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 14:
|
|
|
|
|
|
|
|
for( i = 0; i < 7; i++, RK += 8 )
|
|
|
|
{
|
|
|
|
RK[8] = RK[0] ^ RCON[i] ^
|
|
|
|
( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
|
|
|
|
|
|
|
|
RK[9] = RK[1] ^ RK[8];
|
|
|
|
RK[10] = RK[2] ^ RK[9];
|
|
|
|
RK[11] = RK[3] ^ RK[10];
|
|
|
|
|
|
|
|
RK[12] = RK[4] ^
|
|
|
|
( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
|
|
|
|
( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
|
|
|
|
|
|
|
|
RK[13] = RK[5] ^ RK[12];
|
|
|
|
RK[14] = RK[6] ^ RK[13];
|
|
|
|
RK[15] = RK[7] ^ RK[14];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
static void aeshw_inverse_key(uint8_t *invkey, const uint8_t *fwdkey)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
uint32_t *RK;
|
|
|
|
uint32_t *SK;
|
|
|
|
|
|
|
|
RK = (uint32_t *) invkey;
|
|
|
|
SK = ((uint32_t *) fwdkey) + AES_NR * 4;
|
|
|
|
|
|
|
|
*RK++ = *SK++;
|
|
|
|
*RK++ = *SK++;
|
|
|
|
*RK++ = *SK++;
|
|
|
|
*RK++ = *SK++;
|
|
|
|
|
|
|
|
for( i = AES_NR - 1, SK -= 8; i > 0; i--, SK -= 8 )
|
|
|
|
{
|
|
|
|
for( j = 0; j < 4; j++, SK++ )
|
|
|
|
{
|
|
|
|
*RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
|
|
|
|
RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
|
|
|
|
RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
|
|
|
|
RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*RK++ = *SK++;
|
|
|
|
*RK++ = *SK++;
|
|
|
|
*RK++ = *SK++;
|
|
|
|
*RK++ = *SK++;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_ARM64 */
|
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
#ifdef HAVE_HARDAES
|
|
|
|
static void aeshw_setkey_dec(uint8_t *rk, const uint8_t *key)
|
|
|
|
{
|
|
|
|
uint8_t rk_tmp[AES_RKSIZE];
|
|
|
|
aeshw_setkey_enc(rk_tmp, key);
|
|
|
|
aeshw_inverse_key(rk, rk_tmp);
|
|
|
|
}
|
2017-08-19 13:16:34 +08:00
|
|
|
|
|
|
|
static void aeshw_encrypt_ecb( int nr,
|
|
|
|
unsigned char *rk,
|
|
|
|
const unsigned char input[16],
|
|
|
|
unsigned char output[16] )
|
|
|
|
{
|
|
|
|
aeshw_crypt_ecb(nr, rk, AES_ENCRYPT, input, output);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aeshw_decrypt_ecb( int nr,
|
|
|
|
unsigned char *rk,
|
|
|
|
const unsigned char input[16],
|
|
|
|
unsigned char output[16] )
|
|
|
|
{
|
|
|
|
aeshw_crypt_ecb(nr, rk, AES_DECRYPT, input, output);
|
|
|
|
}
|
2017-08-18 22:27:03 +08:00
|
|
|
#endif /* HAVE_HARDAES */
|
2017-08-18 17:38:24 +08:00
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
/* OpenSSL assembly functions */
|
2017-08-18 17:38:24 +08:00
|
|
|
#define AES_MAXNR 14
|
|
|
|
typedef struct {
|
|
|
|
uint32_t rd_key[4 * (AES_MAXNR + 1)];
|
2017-08-18 22:27:03 +08:00
|
|
|
uint32_t rounds;
|
2017-08-18 17:38:24 +08:00
|
|
|
} AES_KEY;
|
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
#if defined(__amd64__) || defined(__x86_64__) || \
|
|
|
|
defined(__aarch64__)
|
|
|
|
#define AES_set_encrypt_key vpaes_set_encrypt_key
|
|
|
|
#define AES_set_decrypt_key vpaes_set_decrypt_key
|
|
|
|
#define AES_encrypt vpaes_encrypt
|
|
|
|
#define AES_decrypt vpaes_decrypt
|
|
|
|
#endif /* VPAES for 64-bit Intel and ARM */
|
|
|
|
|
2017-08-18 17:38:24 +08:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
|
|
|
|
AES_KEY *key);
|
|
|
|
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
|
|
|
|
AES_KEY *key);
|
|
|
|
|
|
|
|
void AES_encrypt(const unsigned char *in, unsigned char *out,
|
|
|
|
const AES_KEY *key);
|
|
|
|
void AES_decrypt(const unsigned char *in, unsigned char *out,
|
|
|
|
const AES_KEY *key);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-08-19 13:16:34 +08:00
|
|
|
static void aes_encrypt_ecb( int nr,
|
|
|
|
unsigned char *rk,
|
|
|
|
const unsigned char input[16],
|
|
|
|
unsigned char output[16] )
|
2017-08-18 17:38:24 +08:00
|
|
|
{
|
2017-08-19 13:16:34 +08:00
|
|
|
AES_encrypt(input, output, (AES_KEY *) rk);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aes_decrypt_ecb( int nr,
|
|
|
|
unsigned char *rk,
|
|
|
|
const unsigned char input[16],
|
|
|
|
unsigned char output[16] )
|
|
|
|
{
|
|
|
|
AES_decrypt(input, output, (AES_KEY *) rk);
|
2017-08-18 17:38:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void aes_setkey_enc(uint8_t *rk, const uint8_t *key)
|
|
|
|
{
|
2017-08-18 22:27:03 +08:00
|
|
|
AES_set_encrypt_key(key, AES_KEYSIZE, (AES_KEY *) rk);
|
2017-08-18 17:38:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void aes_setkey_dec(uint8_t *rk, const uint8_t *key)
|
|
|
|
{
|
2017-08-18 22:27:03 +08:00
|
|
|
AES_set_decrypt_key(key, AES_KEYSIZE, (AES_KEY *) rk);
|
2017-08-18 17:38:24 +08:00
|
|
|
}
|
|
|
|
|
2017-08-19 13:16:34 +08:00
|
|
|
static void (*encrypt_ecb) ( int nr,
|
|
|
|
unsigned char *rk,
|
|
|
|
const unsigned char input[16],
|
|
|
|
unsigned char output[16] )
|
|
|
|
= aes_encrypt_ecb;
|
|
|
|
|
|
|
|
static void (*decrypt_ecb) ( int nr,
|
|
|
|
unsigned char *rk,
|
|
|
|
const unsigned char input[16],
|
|
|
|
unsigned char output[16] )
|
|
|
|
= aes_decrypt_ecb;
|
2017-08-18 17:38:24 +08:00
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
static void (*setkey_enc) (uint8_t *rk, const uint8_t *key)
|
|
|
|
= aes_setkey_enc;
|
2017-08-18 17:38:24 +08:00
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
static void (*setkey_dec) (uint8_t *rk, const uint8_t *key)
|
|
|
|
= aes_setkey_dec;
|
2017-08-18 17:38:24 +08:00
|
|
|
|
2017-08-18 14:25:14 +08:00
|
|
|
/*
|
|
|
|
* AESNI-CBC buffer encryption/decryption
|
|
|
|
*/
|
2017-08-19 13:16:34 +08:00
|
|
|
static void encrypt_cbc( uint8_t* rk,
|
|
|
|
uint32_t length,
|
|
|
|
uint8_t iv[16],
|
|
|
|
const uint8_t *input,
|
|
|
|
uint8_t *output )
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
uint8_t temp[16];
|
|
|
|
|
2017-08-19 13:16:34 +08:00
|
|
|
while( length > 0 )
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
2017-08-19 13:16:34 +08:00
|
|
|
for( i = 0; i < 16; i++ )
|
|
|
|
output[i] = (uint8_t)( input[i] ^ iv[i] );
|
2017-08-18 14:25:14 +08:00
|
|
|
|
2017-08-19 13:16:34 +08:00
|
|
|
encrypt_ecb( AES_NR, rk, output, output );
|
|
|
|
memcpy( iv, output, 16 );
|
2017-08-18 14:25:14 +08:00
|
|
|
|
2017-08-19 13:16:34 +08:00
|
|
|
input += 16;
|
|
|
|
output += 16;
|
|
|
|
length -= 16;
|
2017-08-18 14:25:14 +08:00
|
|
|
}
|
2017-08-19 13:16:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void decrypt_cbc( uint8_t* rk,
|
|
|
|
uint32_t length,
|
|
|
|
uint8_t iv[16],
|
|
|
|
const uint8_t *input,
|
|
|
|
uint8_t *output )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
uint8_t temp[16];
|
|
|
|
|
|
|
|
while( length > 0 )
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
2017-08-19 13:16:34 +08:00
|
|
|
memcpy( temp, input, 16 );
|
|
|
|
decrypt_ecb( AES_NR, rk, input, output );
|
|
|
|
|
|
|
|
for( i = 0; i < 16; i++ )
|
|
|
|
output[i] = (uint8_t)( output[i] ^ iv[i] );
|
|
|
|
|
|
|
|
memcpy( iv, temp, 16 );
|
|
|
|
|
|
|
|
input += 16;
|
|
|
|
output += 16;
|
|
|
|
length -= 16;
|
2017-08-18 14:25:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
static void aeshw_init(void)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_HARDAES
|
|
|
|
static int done = 0;
|
|
|
|
if (!done) {
|
|
|
|
if (aeshw_supported()) {
|
2017-08-19 13:16:34 +08:00
|
|
|
encrypt_ecb = aeshw_encrypt_ecb;
|
|
|
|
decrypt_ecb = aeshw_decrypt_ecb;
|
2017-08-18 22:27:03 +08:00
|
|
|
setkey_enc = aeshw_setkey_enc;
|
|
|
|
setkey_dec = aeshw_setkey_dec;
|
|
|
|
}
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int AES_support_hwaccel(void)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
2017-08-18 22:27:03 +08:00
|
|
|
#ifdef HAVE_HARDAES
|
|
|
|
return aeshw_supported();
|
2017-08-18 14:25:14 +08:00
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-08-18 19:24:49 +08:00
|
|
|
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
uint8_t iv_tmp[16];
|
2017-09-18 07:10:24 -05:00
|
|
|
static uint8_t rk[AES_RKSIZE];
|
2017-08-18 14:25:14 +08:00
|
|
|
|
2017-09-18 07:10:24 -05:00
|
|
|
if (iv == NULL)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2017-08-18 22:27:03 +08:00
|
|
|
aeshw_init();
|
|
|
|
memcpy(iv_tmp, iv, 16);
|
2017-09-18 07:10:24 -05:00
|
|
|
if(key!= NULL)
|
|
|
|
setkey_enc(rk, key);
|
2017-08-19 13:16:34 +08:00
|
|
|
encrypt_cbc(rk, length, iv_tmp, input, output);
|
2017-08-18 14:25:14 +08:00
|
|
|
}
|
|
|
|
|
2017-08-18 19:24:49 +08:00
|
|
|
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
uint8_t iv_tmp[16];
|
2017-09-18 07:10:24 -05:00
|
|
|
static uint8_t rk[AES_RKSIZE];
|
2017-08-18 14:25:14 +08:00
|
|
|
|
2017-09-18 07:10:24 -05:00
|
|
|
if (iv == NULL)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2017-08-18 22:27:03 +08:00
|
|
|
aeshw_init();
|
|
|
|
memcpy(iv_tmp, iv, 16);
|
2017-09-18 07:10:24 -05:00
|
|
|
if(key!= NULL)
|
|
|
|
{
|
|
|
|
setkey_dec(rk, key);
|
|
|
|
}
|
2017-08-19 13:16:34 +08:00
|
|
|
decrypt_cbc(rk, length, iv_tmp, input, output);
|
2017-08-18 14:25:14 +08:00
|
|
|
}
|
|
|
|
|
2017-08-18 19:24:49 +08:00
|
|
|
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t* output, const uint32_t length)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
uint8_t rk[AES_RKSIZE];
|
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
if (key == NULL)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2017-08-18 22:27:03 +08:00
|
|
|
aeshw_init();
|
|
|
|
setkey_enc(rk, key);
|
2017-08-19 13:16:34 +08:00
|
|
|
encrypt_ecb(AES_NR, rk, input, output);
|
2017-08-18 14:25:14 +08:00
|
|
|
}
|
|
|
|
|
2017-08-18 19:24:49 +08:00
|
|
|
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
uint8_t rk[AES_RKSIZE];
|
|
|
|
|
2017-08-18 22:27:03 +08:00
|
|
|
if (key == NULL)
|
2017-08-18 14:25:14 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2017-08-18 22:27:03 +08:00
|
|
|
aeshw_init();
|
|
|
|
setkey_dec(rk, key);
|
2017-08-19 13:16:34 +08:00
|
|
|
decrypt_ecb(AES_NR, rk, input, output);
|
2017-08-18 14:25:14 +08:00
|
|
|
}
|