Fix standalone libtasn1.
[shishi.git] / crypto / aes.c
blobbf5c827cff5bbfd397002c4e7c303204e57b995c
1 /* aes.c
3 * The aes/rijndael block cipher.
4 */
6 /* nettle, low-level cryptographics library
8 * Copyright (C) 2000, 2001 Rafael R. Sevilla, Niels Möller
9 *
10 * The nettle library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or (at your
13 * option) any later version.
15 * The nettle library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with the nettle library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 * MA 02111-1307, USA.
26 /* Originally written by Rafael R. Sevilla <dido@pacific.net.ph> */
28 #if HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <assert.h>
34 #include "aes-internal.h"
36 #include "macros.h"
38 #ifndef AES_DEBUG
39 # define AES_DEBUG 0
40 #endif
42 #if AES_DEBUG
43 # include <stdio.h>
45 static void
46 d4(const char *name, unsigned r, const uint32_t *data)
48 unsigned j;
50 fprintf(stderr, "aes, %d, %s: ", r, name);
52 for (j = 0; j<4; j++)
53 fprintf(stderr, "%08x, ", data[j]);
54 fprintf(stderr, "\n");
56 static void
57 d2(const char *aname, uint32_t a, const char *bname, uint32_t b)
59 fprintf(stderr, "aes, %s: %08x, %s, %08x\n",
60 aname, a, bname, b);
62 # define D4(x) d4 x
63 # define D2(x) d2 x
64 #else
65 # define D4(x)
66 # define D2(x)
67 #endif
69 /* Get the byte with index 0, 1, 2 and 3 */
70 #define B0(x) ((x) & 0xff)
71 #define B1(x) (((x) >> 8) & 0xff)
72 #define B2(x) (((x) >> 16) & 0xff)
73 #define B3(x) (((x) >> 24) & 0xff)
75 #define IDX0(j) (j)
76 #define IDX1(j) (T->idx[0][j])
77 #define IDX2(j) (T->idx[1][j])
78 #define IDX3(j) (T->idx[2][j])
80 void
81 _aes_crypt(const struct aes_ctx *ctx,
82 const struct aes_table *T,
83 unsigned length, uint8_t *dst,
84 const uint8_t *src)
86 FOR_BLOCKS(length, dst, src, AES_BLOCK_SIZE)
88 uint32_t wtxt[4]; /* working ciphertext */
89 unsigned i;
90 unsigned round;
92 /* Get clear text, using little-endian byte order.
93 * Also XOR with the first subkey. */
94 for (i = 0; i<4; i++)
95 wtxt[i] = LE_READ_UINT32(src + 4*i) ^ ctx->keys[i];
97 for (round = 1; round < ctx->nrounds; round++)
99 uint32_t t[4];
100 unsigned j;
102 D4(("wtxt", round, wtxt));
103 D4(("key", round, &ctx->keys[4*round]));
105 /* What's the best way to order this loop? Ideally,
106 * we'd want to keep both t and wtxt in registers. */
108 for (j=0; j<4; j++)
110 /* FIXME: Figure out how the indexing should really be
111 * done. With the current idx arrays, it looks like the
112 * code shifts the rows in the wrong direction. But it
113 * passes the testsuite. Perhaps the tables are rotated
114 * in the wrong direction, but I don't think so. */
116 #if AES_SMALL
117 t[j] = T->table[0][ B0(wtxt[IDX0(j)]) ] ^
118 ROTRBYTE( T->table[0][ B1(wtxt[IDX1(j)]) ]^
119 ROTRBYTE( T->table[0][ B2(wtxt[IDX2(j)]) ] ^
120 ROTRBYTE(T->table[0][ B3(wtxt[IDX3(j)]) ])));
121 #else /* !AES_SMALL */
122 t[j] = ( T->table[0][ B0(wtxt[IDX0(j)]) ]
123 ^ T->table[1][ B1(wtxt[IDX1(j)]) ]
124 ^ T->table[2][ B2(wtxt[IDX2(j)]) ]
125 ^ T->table[3][ B3(wtxt[IDX3(j)]) ]);
126 #endif /* !AES_SMALL */
128 D4(("t", round, t));
130 for (j = 0; j<4; j++)
131 wtxt[j] = t[j] ^ ctx->keys[4*round + j];
133 /* Final round */
135 uint32_t out;
136 unsigned j;
137 for (j = 0; j<4; j++)
139 /* FIXME: Figure out how the indexing should really be done.
140 * It looks like this code shifts the rows in the wrong
141 * direction, but it passes the testsuite. */
143 out = ( (uint32_t) T->sbox[ B0(wtxt[IDX0(j)]) ]
144 | ((uint32_t) T->sbox[ B1(wtxt[IDX1(j)]) ] << 8)
145 | ((uint32_t) T->sbox[ B2(wtxt[IDX2(j)]) ] << 16)
146 | ((uint32_t) T->sbox[ B3(wtxt[IDX3(j)]) ] << 24));
148 D2(("t", out, "key", ctx->keys[4*round + j]));
150 out ^= ctx->keys[4*round + j];
152 LE_WRITE_UINT32(dst + 4*j, out);