Commit 45da5949 authored by Niels Möller's avatar Niels Möller

(_aes_crypt): New function, which unifies encryption and

decryption.

Rev: src/nettle/aes.c:1.10
parent ddf34204
......@@ -31,12 +31,35 @@
#include <assert.h>
#ifndef DEBUG
# define DEBUG 0
#ifndef AES_DEBUG
# define AES_DEBUG 0
#endif
#if DEBUG
#if AES_DEBUG
# include <stdio.h>
static void
d4(const char *name, unsigned r, const uint32_t *data)
{
unsigned j;
fprintf(stderr, "aes, %d, %s: ", r, name);
for (j = 0; j<4; j++)
fprintf(stderr, "%08x, ", data[j]);
fprintf(stderr, "\n");
}
static void
d2(const char *aname, uint32_t a, const char *bname, uint32_t b)
{
fprintf(stderr, "aes, %s: %08x, %s, %08x\n",
aname, a, bname, b);
}
# define D4(x) d4 x
# define D2(x) d2 x
#else
# define D4(x)
# define D2(x)
#endif
/* Get the byte with index 0, 1, 2 and 3 */
......@@ -45,38 +68,11 @@
#define B2(x) (((x) >> 16) & 0xff)
#define B3(x) (((x) >> 24) & 0xff)
/* Column j are the shifts used when computing t[j].
* Row i is says which byte is used */
/* FIXME: Figure out how the indexing should really be done. It looks
* like this code shifts the rows in the wrong direction, but it
* passes the testsuite. Perhaps the tables are rotated in the wrong
* direction, but I don't think so. */
/* The row shift counts C1, C2 and C3 are (1, 2, 3) */
static const unsigned idx[4][4] = {
{ 0, 1, 2, 3 },
{ 1, 2, 3, 0 },
{ 2, 3, 0, 1 },
{ 3, 0, 1, 2 } };
#if 0
static const unsigned idx4[4][4] = {
{ 0, 4, 8, 12 },
{ 4, 8, 12, 0 },
{ 8, 12, 0, 4 },
{ 12, 0, 4, 8 } };
#endif
static const unsigned iidx[4][4] = {
{ 0, 1, 2, 3 },
{ 3, 0, 1, 2 },
{ 2, 3, 0, 1 },
{ 1, 2, 3, 0 } };
void
aes_encrypt(struct aes_ctx *ctx,
unsigned length, uint8_t *dst,
const uint8_t *src)
_aes_crypt(const struct aes_ctx *ctx,
const struct aes_table *T,
unsigned length, uint8_t *dst,
const uint8_t *src)
{
FOR_BLOCKS(length, dst, src, AES_BLOCK_SIZE)
{
......@@ -94,30 +90,40 @@ aes_encrypt(struct aes_ctx *ctx,
uint32_t t[4];
unsigned j;
D4(("wtxt", round, wtxt));
D4(("key", round, &ctx->keys[4*round]));
/* What's the best way to order this loop? Ideally,
* we'd want to keep both t and wtxt in registers. */
for (j=0; j<4; j++)
{
/* FIXME: Figure out how the indexing should really be
* done. With the current idx arrays, it looks like the
* code shifts the rows in the wrong direction. But it
* passes the testsuite. Perhaps the tables are rotated
* in the wrong direction, but I don't think so. */
#if AES_SMALL
t[j] = dtable[0][ B0(wtxt[j]) ] ^
ROTRBYTE( dtable[0][ B1(wtxt[idx[1][j]]) ]^
ROTRBYTE( dtable[0][ B2(wtxt[idx[2][j]]) ] ^
ROTRBYTE(dtable[0][ B3(wtxt[idx[3][j]]) ])));
t[j] = T->table[0][ B0(wtxt[j]) ] ^
ROTRBYTE( T->table[0][ B1(wtxt[T->idx[0][j]]) ]^
ROTRBYTE( T->table[0][ B2(wtxt[T->idx[1][j]]) ] ^
ROTRBYTE(T->table[0][ B3(wtxt[T->idx[2][j]]) ])));
#else /* !AES_SMALL */
t[j] = ( dtable[0][ B0(wtxt[idx[0][j]]) ]
^ dtable[1][ B1(wtxt[idx[1][j]]) ]
^ dtable[2][ B2(wtxt[idx[2][j]]) ]
^ dtable[3][ B3(wtxt[idx[3][j]]) ]);
t[j] = ( T->table[0][ B0(wtxt[j]) ]
^ T->table[1][ B1(wtxt[T->idx[0][j]]) ]
^ T->table[2][ B2(wtxt[T->idx[1][j]]) ]
^ T->table[3][ B3(wtxt[T->idx[2][j]]) ]);
#endif /* !AES_SMALL */
}
D4(("t", round, t));
for (j = 0; j<4; j++)
wtxt[j] = t[j] ^ ctx->keys[4*round + j];
}
/* Final round */
{
uint32_t cipher;
uint32_t out;
unsigned j;
for (j = 0; j<4; j++)
{
......@@ -125,118 +131,16 @@ aes_encrypt(struct aes_ctx *ctx,
* It looks like this code shifts the rows in the wrong
* direction, but it passes the testsuite. */
cipher = ( (uint32_t) sbox[ B0(wtxt[j]) ]
| ((uint32_t) sbox[ B1(wtxt[idx[1][j]]) ] << 8)
| ((uint32_t) sbox[ B2(wtxt[idx[2][j]]) ] << 16)
| ((uint32_t) sbox[ B3(wtxt[idx[3][j]]) ] << 24));
#if DEBUG
fprintf(stderr, " t[%d]: %x, key: %x\n",
j, cipher, ctx->keys[4*round + j]);
#endif
cipher ^= ctx->keys[4*round + j];
out = ( (uint32_t) T->sbox[ B0(wtxt[j]) ]
| ((uint32_t) T->sbox[ B1(wtxt[T->idx[0][j]]) ] << 8)
| ((uint32_t) T->sbox[ B2(wtxt[T->idx[1][j]]) ] << 16)
| ((uint32_t) T->sbox[ B3(wtxt[T->idx[2][j]]) ] << 24));
LE_WRITE_UINT32(dst + 4*j, cipher);
}
}
}
}
D2(("t", out, "key", ctx->keys[4*round + j]));
void
aes_decrypt(struct aes_ctx *ctx,
unsigned length, uint8_t *dst,
const uint8_t *src)
{
#if DEBUG
{
unsigned i, j;
fprintf(stderr, "subkeys:\n");
for (j = 0; j<=ctx->nrounds; j++)
{
printf(" %d: ", j);
for (i = 0; i<4; i++)
printf("%08x, ", ctx->ikeys[i + 4*j]);
printf("\n");
}
}
#endif
FOR_BLOCKS(length, dst, src, AES_BLOCK_SIZE)
{
uint32_t wtxt[4]; /* working ciphertext */
unsigned i;
unsigned round;
/* Get cipher text, using little-endian byte order.
* Also XOR with the first subkey. */
for (i = 0; i<4; i++)
wtxt[i] = LE_READ_UINT32(src + 4*i) ^ ctx->ikeys[i];
for (round = 1; round < ctx->nrounds; round++)
{
uint32_t t[4];
unsigned j;
#if DEBUG
fprintf(stderr, "decrypt, round: %d\n wtxt: ", round);
for (j = 0; j<4; j++)
fprintf(stderr, "%08x, ", wtxt[j]);
fprintf(stderr, "\n key: ");
for (j = 0; j<4; j++)
fprintf(stderr, "%08x, ", ctx->ikeys[4*round + j]);
fprintf(stderr, "\n");
#endif
/* The row shift counts C1, C2 and C3 are (1, 2, 3) */
/* What's the best way to order this loop? Ideally,
* we'd want to keep both t and wtxt in registers. */
for (j=0; j<4; j++)
{
#if AES_SMALL
t[j] = itable[0][ B0(wtxt[j]) ] ^
ROTRBYTE( itable[0][ B1(wtxt[iidx[1][j]]) ]^
ROTRBYTE( itable[0][ B2(wtxt[iidx[2][j]]) ] ^
ROTRBYTE(itable[0][ B3(wtxt[iidx[3][j]]) ])));
#else /* !AES_SMALL */
/* FIXME: Figure out how the indexing should really be done.
* It looks like this code shifts the rows in the wrong
* direction, but it passes the testsuite. */
for (j=0; j<4; j++)
t[j] = ( itable[0][ B0(wtxt[iidx[0][j]]) ]
^ itable[1][ B1(wtxt[iidx[1][j]]) ]
^ itable[2][ B2(wtxt[iidx[2][j]]) ]
^ itable[3][ B3(wtxt[iidx[3][j]]) ]);
#endif /* !AES_SMALL */
}
#if DEBUG
fprintf(stderr, " t: ");
for (j = 0; j<4; j++)
fprintf(stderr, "%08x, ", t[j]);
fprintf(stderr, "\n");
#endif
for (j = 0; j<4; j++)
wtxt[j] = t[j] ^ ctx->ikeys[4*round + j];
}
/* Final round */
{
uint32_t clear;
unsigned j;
for (j = 0; j<4; j++)
{
/* FIXME: Figure out how the indexing should really be done.
* It looks like this code shifts the rows in the wrong
* direction, but it passes the testsuite. */
clear = ( (uint32_t) isbox[ B0(wtxt[j]) ]
| ((uint32_t) isbox[ B1(wtxt[iidx[1][j]]) ] << 8)
| ((uint32_t) isbox[ B2(wtxt[iidx[2][j]]) ] << 16)
| ((uint32_t) isbox[ B3(wtxt[iidx[3][j]]) ] << 24));
#if DEBUG
fprintf(stderr, " t[%d]: %x, key: %x\n",
j, clear, ctx->ikeys[4*round + j]);
#endif
clear ^= ctx->ikeys[4*round + j];
out ^= ctx->keys[4*round + j];
LE_WRITE_UINT32(dst + 4*j, clear);
LE_WRITE_UINT32(dst + 4*j, out);
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment