Jump to content
Nytro

[C] AES Implementation

Recommended Posts

[h=1][C] AES Implementation[/h][h=3]X-N2O[/h]I joined all the source inside the code tags.

If you wanna use it you have the separate files aes.c, aes.h and main.c inside the zip file.

Enjoy.

// AES Implementation by X-N2O

// Started: 15:41:35 - 18 Nov 2009

// Finished: 20:03:59 - 21 Nov 2009

// Logarithm, S-Box, and RCON tables are not hardcoded

// Instead they are generated when the program starts

// All of the code below is based from the AES specification

// You can find it at http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf

// You may use this code as you wish, but do not remove this comment

// This is only a proof of concept, and should not be considered as the most efficient implementation

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

#define AES_RPOL 0x011b // reduction polynomial (x^8 + x^4 + x^3 + x + 1)

#define AES_GEN 0x03 // gf(2^8) generator (x + 1)

#define AES_SBOX_CC 0x63 // S-Box C constant

#define KEY_128 (128/8)

#define KEY_192 (192/8)

#define KEY_256 (256/8)

#define aes_mul(a, B) ((a)&&(B)?g_aes_ilogt[(g_aes_logt[(a)]+g_aes_logt[(B)])%0xff]:0)

#define aes_inv(a) ((a)?g_aes_ilogt[0xff-g_aes_logt[(a)]]:0)

unsigned char g_aes_logt[256], g_aes_ilogt[256];

unsigned char g_aes_sbox[256], g_aes_isbox[256];

typedef struct {

unsigned char state[4][4];

int kcol;

size_t rounds;

unsigned long keysched[0];

} aes_ctx_t;

void aes_init();

aes_ctx_t *aes_alloc_ctx(unsigned char *key, size_t keyLen);

inline unsigned long aes_subword(unsigned long w);

inline unsigned long aes_rotword(unsigned long w);

void aes_keyexpansion(aes_ctx_t *ctx);

inline unsigned char aes_mul_manual(unsigned char a, unsigned char B); // use aes_mul instead

void aes_subbytes(aes_ctx_t *ctx);

void aes_shiftrows(aes_ctx_t *ctx);

void aes_mixcolumns(aes_ctx_t *ctx);

void aes_addroundkey(aes_ctx_t *ctx, int round);

void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16]);

void aes_invsubbytes(aes_ctx_t *ctx);

void aes_invshiftrows(aes_ctx_t *ctx);

void aes_invmixcolumns(aes_ctx_t *ctx);

void aes_decrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16]);

void aes_free_ctx(aes_ctx_t *ctx);

void init_aes()

{

int i;

unsigned char gen;

// build logarithm table and it's inverse

gen = 1;

for(i = 0; i < 0xff; i++) {

g_aes_logt[gen] = i;

g_aes_ilogt = gen;

gen = aes_mul_manual(gen, AES_GEN);

}

// build S-Box and it's inverse

for(i = 0; i <= 0xff; i++) {

char bi;

unsigned char inv = aes_inv(i);

g_aes_sbox = 0;

for(bi = 0; bi < 8; bi++) {

// based on transformation 5.1

// could also be done with a loop based on the matrix

g_aes_sbox |= ((inv & (1<<bi)?1:0)

^ (inv & (1 << ((bi+4) & 7))?1:0)

^ (inv & (1 << ((bi+5) & 7))?1:0)

^ (inv & (1 << ((bi+6) & 7))?1:0)

^ (inv & (1 << ((bi+7) & 7))?1:0)

^ (AES_SBOX_CC & (1 << bi)?1:0)

) << bi;

}

g_aes_isbox[g_aes_sbox] = i;

}

// warning: quickhack

g_aes_sbox[1] = 0x7c;

g_aes_isbox[0x7c] = 1;

g_aes_isbox[0x63] = 0;

}

aes_ctx_t *aes_alloc_ctx(unsigned char *key, size_t keyLen)

{

aes_ctx_t *ctx;

size_t rounds;

size_t ks_size;

switch(keyLen) {

case 16: // 128-bit key

rounds = 10;

break;

case 24: // 192-bit key

rounds = 12;

break;

case 32: // 256-bit key

rounds = 14;

break;

defaut:

return NULL;

}

ks_size = 4*(rounds+1)*sizeof(unsigned long);

ctx = malloc(sizeof(aes_ctx_t)+ks_size);

if(ctx) {

ctx->rounds = rounds;

ctx->kcol = keyLen/4;

memcpy(ctx->keysched, key, keyLen);

ctx->keysched[43] = 0;

aes_keyexpansion(ctx);

}

return ctx;

}

inline unsigned long aes_subword(unsigned long w)

{

return g_aes_sbox[w & 0x000000ff] |

(g_aes_sbox[(w & 0x0000ff00) >> 8] << 8) |

(g_aes_sbox[(w & 0x00ff0000) >> 16] << 16) |

(g_aes_sbox[(w & 0xff000000) >> 24] << 24);

}

inline unsigned long aes_rotword(unsigned long w)

{

// May seem a bit different from the spec

// It was changed because unsigned long is represented with little-endian convention on x86

// Should not depend on architecture, but this is only a POC

return ((w & 0x000000ff) << 24) |

((w & 0x0000ff00) >> 8) |

((w & 0x00ff0000) >> 8) |

((w & 0xff000000) >> 8);

}

void aes_keyexpansion(aes_ctx_t *ctx)

{

unsigned long temp;

unsigned long rcon;

register int i;

rcon = 0x00000001;

for(i = ctx->kcol; i < (4*(ctx->rounds+1)); i++) {

temp = ctx->keysched[i-1];

if(!(i%ctx->kcol)) {

temp = aes_subword(aes_rotword(temp)) ^ rcon;

rcon = aes_mul(rcon, 2);

} else if(ctx->kcol > 6 && i%ctx->kcol == 4)

temp = aes_subword(temp);

ctx->keysched = ctx->keysched[i-ctx->kcol] ^ temp;

}

}

inline unsigned char aes_mul_manual(unsigned char a, unsigned char B)

{

register unsigned short ac;

register unsigned char ret;

ac = a;

ret = 0;

while(B) {

if(b & 0x01)

ret ^= ac;

ac <<= 1;

b >>= 1;

if(ac & 0x0100)

ac ^= AES_RPOL;

}

return ret;

}

void aes_subbytes(aes_ctx_t *ctx)

{

int i;

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

int x, y;

x = i & 0x03;

y = i >> 2;

ctx->state[x][y] = g_aes_sbox[ctx->state[x][y]];

}

}

void aes_shiftrows(aes_ctx_t *ctx)

{

unsigned char nstate[4][4];

int i;

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

int x, y;

x = i & 0x03;

y = i >> 2;

nstate[x][y] = ctx->state[x][(y+x) & 0x03];

}

memcpy(ctx->state, nstate, sizeof(ctx->state));

}

void aes_mixcolumns(aes_ctx_t *ctx)

{

unsigned char nstate[4][4];

int i;

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

nstate[0] = aes_mul(0x02, ctx->state[0]) ^

aes_mul(0x03, ctx->state[1]) ^

ctx->state[2] ^

ctx->state[3];

nstate[1] = ctx->state[0] ^

aes_mul(0x02, ctx->state[1]) ^

aes_mul(0x03, ctx->state[2]) ^

ctx->state[3];

nstate[2] = ctx->state[0] ^

ctx->state[1] ^

aes_mul(0x02, ctx->state[2]) ^

aes_mul(0x03, ctx->state[3]);

nstate[3] = aes_mul(0x03, ctx->state[0]) ^

ctx->state[1] ^

ctx->state[2] ^

aes_mul(0x02, ctx->state[3]);

}

memcpy(ctx->state, nstate, sizeof(ctx->state));

}

void aes_addroundkey(aes_ctx_t *ctx, int round)

{

int i;

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

int x, y;

x = i & 0x03;

y = i >> 2;

ctx->state[x][y] = ctx->state[x][y] ^

((ctx->keysched[round*4+y] & (0xff << (x*8))) >> (x*8));

}

}

void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16])

{

int i;

// copy input to state

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

ctx->state[i & 0x03][i >> 2] = input;

aes_addroundkey(ctx, 0);

for(i = 1; i < ctx->rounds; i++) {

aes_subbytes(ctx);

aes_shiftrows(ctx);

aes_mixcolumns(ctx);

aes_addroundkey(ctx, i);

}

aes_subbytes(ctx);

aes_shiftrows(ctx);

aes_addroundkey(ctx, ctx->rounds);

// copy state to output

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

output = ctx->state[i & 0x03][i >> 2];

}

void aes_invshiftrows(aes_ctx_t *ctx)

{

unsigned char nstate[4][4];

int i;

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

int x, y;

x = i & 0x03;

y = i >> 2;

nstate[x][(y+x) & 0x03] = ctx->state[x][y];

}

memcpy(ctx->state, nstate, sizeof(ctx->state));

}

void aes_invsubbytes(aes_ctx_t *ctx)

{

int i;

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

int x, y;

x = i & 0x03;

y = i >> 2;

ctx->state[x][y] = g_aes_isbox[ctx->state[x][y]];

}

}

void aes_invmixcolumns(aes_ctx_t *ctx)

{

unsigned char nstate[4][4];

int i;

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

nstate[0] = aes_mul(0x0e, ctx->state[0]) ^

aes_mul(0x0b, ctx->state[1]) ^

aes_mul(0x0d, ctx->state[2]) ^

aes_mul(0x09, ctx->state[3]);

nstate[1] = aes_mul(0x09, ctx->state[0]) ^

aes_mul(0x0e, ctx->state[1]) ^

aes_mul(0x0b, ctx->state[2]) ^

aes_mul(0x0d, ctx->state[3]);

nstate[2] = aes_mul(0x0d, ctx->state[0]) ^

aes_mul(0x09, ctx->state[1]) ^

aes_mul(0x0e, ctx->state[2]) ^

aes_mul(0x0b, ctx->state[3]);

nstate[3] = aes_mul(0x0b, ctx->state[0]) ^

aes_mul(0x0d, ctx->state[1]) ^

aes_mul(0x09, ctx->state[2]) ^

aes_mul(0x0e, ctx->state[3]);

}

memcpy(ctx->state, nstate, sizeof(ctx->state));

}

void aes_decrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16])

{

int i, j;

// copy input to state

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

ctx->state[i & 0x03][i >> 2] = input;

aes_addroundkey(ctx, ctx->rounds);

for(i = ctx->rounds-1; i >= 1; i--) {

aes_invshiftrows(ctx);

aes_invsubbytes(ctx);

aes_addroundkey(ctx, i);

aes_invmixcolumns(ctx);

}

aes_invshiftrows(ctx);

aes_invsubbytes(ctx);

aes_addroundkey(ctx, 0);

// copy state to output

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

output = ctx->state[i & 0x03][i >> 2];

}

void aes_free_ctx(aes_ctx_t *ctx)

{

free(ctx);

}

int main(int argc, char *argv[])

{

unsigned char key[KEY_128] = "uber strong key!";

unsigned char ptext[16] = "Attack at dawn!";

unsigned char ctext[16];

unsigned char decptext[16];

aes_ctx_t *ctx;

init_aes();

ctx = aes_alloc_ctx(key, sizeof(key));

if(!ctx) {

perror("aes_alloc_ctx");

return EXIT_FAILURE;

}

aes_encrypt(ctx, ptext, ctext);

aes_decrypt(ctx, ctext, decptext);

puts(decptext);

aes_free_ctx(ctx);

return EXIT_SUCCESS;

}

In the attached zip you will also find the compiled ELF binary.

zip.gif aes.zip 8.84KB 2183 downloads

Sursa: [C] AES Implementation - Professional Code - rohitab.com - Forums

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...