Add support for using 192-bit and 256-bit keys with AES-GCM

This adds 192-bit and 256-bit key support to the internal AES
implementation and extends the AES-GCM functions to accept key length to
enable longer AES key use.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-09-09 12:26:22 +03:00
parent af0963fab4
commit d140db6adf
8 changed files with 258 additions and 65 deletions

View file

@ -1,5 +1,5 @@
/*
* Galois/Counter Mode (GCM) and GMAC with AES-128
* Galois/Counter Mode (GCM) and GMAC with AES
*
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
*
@ -173,18 +173,18 @@ static void aes_gctr(void *aes, const u8 *icb, const u8 *x, size_t xlen, u8 *y)
/**
* aes_128_gcm_ae - GCM-AE_K(IV, P, A)
* aes_gcm_ae - GCM-AE_K(IV, P, A)
*/
int aes_128_gcm_ae(const u8 *key, const u8 *iv, size_t iv_len,
const u8 *plain, size_t plain_len,
const u8 *aad, size_t aad_len, u8 *crypt, u8 *tag)
int aes_gcm_ae(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len,
const u8 *plain, size_t plain_len,
const u8 *aad, size_t aad_len, u8 *crypt, u8 *tag)
{
u8 H[AES_BLOCK_SIZE];
u8 J0[AES_BLOCK_SIZE], J0inc[AES_BLOCK_SIZE];
u8 S[16], len_buf[16];
void *aes;
aes = aes_encrypt_init(key, 16);
aes = aes_encrypt_init(key, key_len);
if (aes == NULL)
return -1;
@ -242,18 +242,18 @@ int aes_128_gcm_ae(const u8 *key, const u8 *iv, size_t iv_len,
/**
* aes_128_gcm_ad - GCM-AD_K(IV, C, A, T)
* aes_gcm_ad - GCM-AD_K(IV, C, A, T)
*/
int aes_128_gcm_ad(const u8 *key, const u8 *iv, size_t iv_len,
const u8 *crypt, size_t crypt_len,
const u8 *aad, size_t aad_len, const u8 *tag, u8 *plain)
int aes_gcm_ad(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len,
const u8 *crypt, size_t crypt_len,
const u8 *aad, size_t aad_len, const u8 *tag, u8 *plain)
{
u8 H[AES_BLOCK_SIZE];
u8 J0[AES_BLOCK_SIZE], J0inc[AES_BLOCK_SIZE];
u8 S[16], T[16], len_buf[16];
void *aes;
aes = aes_encrypt_init(key, 16);
aes = aes_encrypt_init(key, key_len);
if (aes == NULL)
return -1;

View file

@ -2,14 +2,13 @@
* AES (Rijndael) cipher - decrypt
*
* Modifications to public domain implementation:
* - support only 128-bit keys
* - cleanup
* - use C pre-processor to make it easier to change S table access
* - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
* cost of reduced throughput (quite small difference on Pentium 4,
* 10-25% when using -O1 or -O2 optimization)
*
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -26,13 +25,15 @@
*
* @return the number of rounds for the given cipher key size.
*/
static void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
static int rijndaelKeySetupDec(u32 rk[], const u8 cipherKey[], int keyBits)
{
int Nr = 10, i, j;
int Nr, i, j;
u32 temp;
/* expand the cipher key: */
rijndaelKeySetupEnc(rk, cipherKey);
Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
if (Nr < 0)
return Nr;
/* invert the order of the round keys: */
for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
@ -51,24 +52,30 @@ static void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
TD3_(TE4((rk[j] ) & 0xff));
}
}
return Nr;
}
void * aes_decrypt_init(const u8 *key, size_t len)
{
u32 *rk;
if (len != 16)
return NULL;
int res;
rk = os_malloc(AES_PRIV_SIZE);
if (rk == NULL)
return NULL;
rijndaelKeySetupDec(rk, key);
res = rijndaelKeySetupDec(rk, key, len * 8);
if (res < 0) {
os_free(rk);
return NULL;
}
rk[AES_PRIV_NR_POS] = res;
return rk;
}
static void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16])
static void rijndaelDecrypt(const u32 rk[/*44*/], int Nr, const u8 ct[16],
u8 pt[16])
{
u32 s0, s1, s2, s3, t0, t1, t2, t3;
const int Nr = 10;
#ifndef FULL_UNROLL
int r;
#endif /* ?FULL_UNROLL */
@ -99,6 +106,14 @@ d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
ROUND(7,t,s);
ROUND(8,s,t);
ROUND(9,t,s);
if (Nr > 10) {
ROUND(10,s,t);
ROUND(11,t,s);
if (Nr > 12) {
ROUND(12,s,t);
ROUND(13,t,s);
}
}
rk += Nr << 2;
@ -134,7 +149,8 @@ d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
{
rijndaelDecrypt(ctx, crypt, plain);
u32 *rk = ctx;
rijndaelDecrypt(ctx, rk[AES_PRIV_NR_POS], crypt, plain);
}

View file

@ -2,14 +2,13 @@
* AES (Rijndael) cipher - encrypt
*
* Modifications to public domain implementation:
* - support only 128-bit keys
* - cleanup
* - use C pre-processor to make it easier to change S table access
* - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
* cost of reduced throughput (quite small difference on Pentium 4,
* 10-25% when using -O1 or -O2 optimization)
*
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -21,10 +20,9 @@
#include "crypto.h"
#include "aes_i.h"
static void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
static void rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16])
{
u32 s0, s1, s2, s3, t0, t1, t2, t3;
const int Nr = 10;
#ifndef FULL_UNROLL
int r;
#endif /* ?FULL_UNROLL */
@ -55,6 +53,14 @@ d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
ROUND(7,t,s);
ROUND(8,s,t);
ROUND(9,t,s);
if (Nr > 10) {
ROUND(10,s,t);
ROUND(11,t,s);
if (Nr > 12) {
ROUND(12,s,t);
ROUND(13,t,s);
}
}
rk += Nr << 2;
@ -92,19 +98,24 @@ d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
void * aes_encrypt_init(const u8 *key, size_t len)
{
u32 *rk;
if (len != 16)
return NULL;
int res;
rk = os_malloc(AES_PRIV_SIZE);
if (rk == NULL)
return NULL;
rijndaelKeySetupEnc(rk, key);
res = rijndaelKeySetupEnc(rk, key, len * 8);
if (res < 0) {
os_free(rk);
return NULL;
}
rk[AES_PRIV_NR_POS] = res;
return rk;
}
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
{
rijndaelEncrypt(ctx, plain, crypt);
u32 *rk = ctx;
rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt);
}

View file

@ -2,14 +2,13 @@
* AES (Rijndael) cipher
*
* Modifications to public domain implementation:
* - support only 128-bit keys
* - cleanup
* - use C pre-processor to make it easier to change S table access
* - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
* cost of reduced throughput (quite small difference on Pentium 4,
* 10-25% when using -O1 or -O2 optimization)
*
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -777,7 +776,7 @@ const u8 rcons[] = {
*
* @return the number of rounds for the given cipher key size.
*/
void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits)
{
int i;
u32 temp;
@ -786,14 +785,61 @@ void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
rk[1] = GETU32(cipherKey + 4);
rk[2] = GETU32(cipherKey + 8);
rk[3] = GETU32(cipherKey + 12);
for (i = 0; i < 10; i++) {
temp = rk[3];
rk[4] = rk[0] ^
TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^
RCON(i);
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
rk += 4;
if (keyBits == 128) {
for (i = 0; i < 10; i++) {
temp = rk[3];
rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
TE443(temp) ^ TE414(temp) ^ RCON(i);
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
rk += 4;
}
return 10;
}
rk[4] = GETU32(cipherKey + 16);
rk[5] = GETU32(cipherKey + 20);
if (keyBits == 192) {
for (i = 0; i < 8; i++) {
temp = rk[5];
rk[6] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
TE443(temp) ^ TE414(temp) ^ RCON(i);
rk[7] = rk[1] ^ rk[6];
rk[8] = rk[2] ^ rk[7];
rk[9] = rk[3] ^ rk[8];
if (i == 7)
return 12;
rk[10] = rk[4] ^ rk[9];
rk[11] = rk[5] ^ rk[10];
rk += 6;
}
}
rk[6] = GETU32(cipherKey + 24);
rk[7] = GETU32(cipherKey + 28);
if (keyBits == 256) {
for (i = 0; i < 7; i++) {
temp = rk[7];
rk[8] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
TE443(temp) ^ TE414(temp) ^ RCON(i);
rk[9] = rk[1] ^ rk[8];
rk[10] = rk[2] ^ rk[9];
rk[11] = rk[3] ^ rk[10];
if (i == 6)
return 14;
temp = rk[11];
rk[12] = rk[4] ^ TE411(temp) ^ TE422(temp) ^
TE433(temp) ^ TE444(temp);
rk[13] = rk[5] ^ rk[12];
rk[14] = rk[6] ^ rk[13];
rk[15] = rk[7] ^ rk[14];
rk += 8;
}
}
return -1;
}

View file

@ -1,6 +1,6 @@
/*
* AES (Rijndael) cipher
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -44,6 +44,10 @@ extern const u8 rcons[10];
#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
#define TE411(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
#define TE422(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
#define TE433(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
#define TE444(i) (Te4[(i) & 0xff] & 0x000000ff)
#define TE4(i) (Te4[(i)] & 0x000000ff)
#define TD0(i) Td0[((i) >> 24) & 0xff]
@ -80,6 +84,10 @@ static inline u32 rotr(u32 val, int bits)
#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
#define TE411(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
#define TE422(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
#define TE433(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
#define TE444(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
#define TD0(i) Td0[((i) >> 24) & 0xff]
@ -109,8 +117,9 @@ static inline u32 rotr(u32 val, int bits)
(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
#endif
#define AES_PRIV_SIZE (4 * 44)
#define AES_PRIV_SIZE (4 * 4 * 15 + 4)
#define AES_PRIV_NR_POS (4 * 15)
void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]);
int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits);
#endif /* AES_I_H */

View file

@ -6,7 +6,7 @@
* - AES-128 CTR mode encryption
* - AES-128 EAX mode encryption/decryption
* - AES-128 CBC
* - AES-128 GCM
* - AES-GCM
*
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
@ -39,13 +39,15 @@ int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
size_t data_len);
int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
size_t data_len);
int __must_check aes_128_gcm_ae(const u8 *key, const u8 *iv, size_t iv_len,
const u8 *plain, size_t plain_len,
const u8 *aad, size_t aad_len,
u8 *crypt, u8 *tag);
int __must_check aes_128_gcm_ad(const u8 *key, const u8 *iv, size_t iv_len,
const u8 *crypt, size_t crypt_len,
const u8 *aad, size_t aad_len, const u8 *tag,
u8 *plain);
int __must_check aes_gcm_ae(const u8 *key, size_t key_len,
const u8 *iv, size_t iv_len,
const u8 *plain, size_t plain_len,
const u8 *aad, size_t aad_len,
u8 *crypt, u8 *tag);
int __must_check aes_gcm_ad(const u8 *key, size_t key_len,
const u8 *iv, size_t iv_len,
const u8 *crypt, size_t crypt_len,
const u8 *aad, size_t aad_len, const u8 *tag,
u8 *plain);
#endif /* AES_WRAP_H */