#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 */
#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)
{
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++)
{
* 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);
}
}
}