]>
git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/utilLib/rijndael-alg-ref.c
1 /* rijndael-alg-ref.c v2.0 August '99
2 * Reference ANSI C code
3 * authors: Paulo Barreto
10 #include "rijndael-alg-ref.h"
12 #define SC ((BC - 4) >> 1)
14 #include "boxes-ref.h"
16 static const word8 shifts
[3][4][2] = {
35 static word8
mul(word8 a
, word8 b
) {
36 /* multiply two elements of GF(2^m)
37 * needed for MixColumn and InvMixColumn
39 if (a
&& b
) return Alogtable
[(Logtable
[a
] + Logtable
[b
])%255
];
43 static void KeyAddition(word8 a
[4][MAXBC
], word8 rk
[4][MAXBC
], word8 BC
) {
44 /* Exor corresponding text input and round key input bytes
48 for(i
= 0; i
< 4; i
++)
49 for(j
= 0; j
< BC
; j
++) a
[i
][j
] ^= rk
[i
][j
];
52 static void ShiftRow(word8 a
[4][MAXBC
], word8 d
, word8 BC
) {
53 /* Row 0 remains unchanged
54 * The other three rows are shifted a variable amount
59 for(i
= 1; i
< 4; i
++) {
60 for(j
= 0; j
< BC
; j
++) tmp
[j
] = a
[i
][(j
+ shifts
[SC
][i
][d
]) % BC
];
61 for(j
= 0; j
< BC
; j
++) a
[i
][j
] = tmp
[j
];
65 static void Substitution(word8 a
[4][MAXBC
], const word8 box
[256], word8 BC
) {
66 /* Replace every byte of the input by the byte at that place
67 * in the nonlinear S-box
71 for(i
= 0; i
< 4; i
++)
72 for(j
= 0; j
< BC
; j
++) a
[i
][j
] = box
[a
[i
][j
]] ;
75 static void MixColumn(word8 a
[4][MAXBC
], word8 BC
) {
76 /* Mix the four bytes of every column in a linear way
81 for(j
= 0; j
< BC
; j
++)
82 for(i
= 0; i
< 4; i
++)
83 b
[i
][j
] = mul(2,a
[i
][j
])
84 ^ mul(3,a
[(i
+ 1) % 4][j
])
87 for(i
= 0; i
< 4; i
++)
88 for(j
= 0; j
< BC
; j
++) a
[i
][j
] = b
[i
][j
];
91 static void InvMixColumn(word8 a
[4][MAXBC
], word8 BC
) {
92 /* Mix the four bytes of every column in a linear way
93 * This is the opposite operation of Mixcolumn
98 for(j
= 0; j
< BC
; j
++)
99 for(i
= 0; i
< 4; i
++)
100 b
[i
][j
] = mul(0xe,a
[i
][j
])
101 ^ mul(0xb,a
[(i
+ 1) % 4][j
])
102 ^ mul(0xd,a
[(i
+ 2) % 4][j
])
103 ^ mul(0x9,a
[(i
+ 3) % 4][j
]);
104 for(i
= 0; i
< 4; i
++)
105 for(j
= 0; j
< BC
; j
++) a
[i
][j
] = b
[i
][j
];
108 int _rijndaelKeySched (word8 k
[4][MAXKC
], int keyBits
, int blockBits
, word8 W
[MAXROUNDS
+1][4][MAXBC
]) {
109 /* Calculate the necessary round keys
110 * The number of calculations depends on keyBits and blockBits
113 int i
, j
, t
, rconpointer
= 0;
117 case 128: KC
= 4; break;
118 case 192: KC
= 6; break;
119 case 256: KC
= 8; break;
120 default : return (-1);
124 case 128: BC
= 4; break;
125 case 192: BC
= 6; break;
126 case 256: BC
= 8; break;
127 default : return (-2);
130 switch (keyBits
>= blockBits
? keyBits
: blockBits
) {
131 case 128: ROUNDS
= 10; break;
132 case 192: ROUNDS
= 12; break;
133 case 256: ROUNDS
= 14; break;
134 default : return (-3); /* this cannot happen */
138 for(j
= 0; j
< KC
; j
++)
139 for(i
= 0; i
< 4; i
++)
142 /* copy values into round key array */
143 for(j
= 0; (j
< KC
) && (t
< (ROUNDS
+1)*BC
); j
++, t
++)
144 for(i
= 0; i
< 4; i
++) W
[t
/ BC
][i
][t
% BC
] = tk
[i
][j
];
146 while (t
< (ROUNDS
+1)*BC
) { /* while not enough round key material calculated */
147 /* calculate new values */
148 for(i
= 0; i
< 4; i
++)
149 tk
[i
][0] ^= S
[tk
[(i
+1)%4
][KC
-1]];
150 tk
[0][0] ^= rcon
[rconpointer
++];
153 for(j
= 1; j
< KC
; j
++)
154 for(i
= 0; i
< 4; i
++) tk
[i
][j
] ^= tk
[i
][j
-1];
156 for(j
= 1; j
< KC
/2; j
++)
157 for(i
= 0; i
< 4; i
++) tk
[i
][j
] ^= tk
[i
][j
-1];
158 for(i
= 0; i
< 4; i
++) tk
[i
][KC
/2] ^= S
[tk
[i
][KC
/2 - 1]];
159 for(j
= KC
/2 + 1; j
< KC
; j
++)
160 for(i
= 0; i
< 4; i
++) tk
[i
][j
] ^= tk
[i
][j
-1];
162 /* copy values into round key array */
163 for(j
= 0; (j
< KC
) && (t
< (ROUNDS
+1)*BC
); j
++, t
++)
164 for(i
= 0; i
< 4; i
++) W
[t
/ BC
][i
][t
% BC
] = tk
[i
][j
];
170 int _rijndaelEncrypt (word8 a
[4][MAXBC
], int keyBits
, int blockBits
, word8 rk
[MAXROUNDS
+1][4][MAXBC
])
172 /* Encryption of one block.
177 case 128: BC
= 4; break;
178 case 192: BC
= 6; break;
179 case 256: BC
= 8; break;
180 default : return (-2);
183 switch (keyBits
>= blockBits
? keyBits
: blockBits
) {
184 case 128: ROUNDS
= 10; break;
185 case 192: ROUNDS
= 12; break;
186 case 256: ROUNDS
= 14; break;
187 default : return (-3); /* this cannot happen */
190 /* begin with a key addition
192 KeyAddition(a
,rk
[0],BC
);
194 /* ROUNDS-1 ordinary rounds
196 for(r
= 1; r
< ROUNDS
; r
++) {
197 Substitution(a
,S
,BC
);
200 KeyAddition(a
,rk
[r
],BC
);
203 /* Last round is special: there is no MixColumn
205 Substitution(a
,S
,BC
);
207 KeyAddition(a
,rk
[ROUNDS
],BC
);
215 int rijndaelEncryptRound (word8 a
[4][MAXBC
], int keyBits
, int blockBits
,
216 word8 rk
[MAXROUNDS
+1][4][MAXBC
], int rounds
)
217 /* Encrypt only a certain number of rounds.
218 * Only used in the Intermediate Value Known Answer Test.
224 case 128: BC
= 4; break;
225 case 192: BC
= 6; break;
226 case 256: BC
= 8; break;
227 default : return (-2);
230 switch (keyBits
>= blockBits
? keyBits
: blockBits
) {
231 case 128: ROUNDS
= 10; break;
232 case 192: ROUNDS
= 12; break;
233 case 256: ROUNDS
= 14; break;
234 default : return (-3); /* this cannot happen */
237 /* make number of rounds sane */
238 if (rounds
> ROUNDS
) rounds
= ROUNDS
;
240 /* begin with a key addition
242 KeyAddition(a
,rk
[0],BC
);
244 /* at most ROUNDS-1 ordinary rounds
246 for(r
= 1; (r
<= rounds
) && (r
< ROUNDS
); r
++) {
247 Substitution(a
,S
,BC
);
250 KeyAddition(a
,rk
[r
],BC
);
253 /* if necessary, do the last, special, round:
255 if (rounds
== ROUNDS
) {
256 Substitution(a
,S
,BC
);
258 KeyAddition(a
,rk
[ROUNDS
],BC
);
263 #endif /* __APPLE__ */
265 int _rijndaelDecrypt (word8 a
[4][MAXBC
], int keyBits
, int blockBits
, word8 rk
[MAXROUNDS
+1][4][MAXBC
])
270 case 128: BC
= 4; break;
271 case 192: BC
= 6; break;
272 case 256: BC
= 8; break;
273 default : return (-2);
276 switch (keyBits
>= blockBits
? keyBits
: blockBits
) {
277 case 128: ROUNDS
= 10; break;
278 case 192: ROUNDS
= 12; break;
279 case 256: ROUNDS
= 14; break;
280 default : return (-3); /* this cannot happen */
283 /* To decrypt: apply the inverse operations of the encrypt routine,
286 * (KeyAddition is an involution: it 's equal to its inverse)
287 * (the inverse of Substitution with table S is Substitution with the inverse table of S)
288 * (the inverse of Shiftrow is Shiftrow over a suitable distance)
291 /* First the special round:
292 * without InvMixColumn
293 * with extra KeyAddition
295 KeyAddition(a
,rk
[ROUNDS
],BC
);
296 Substitution(a
,Si
,BC
);
299 /* ROUNDS-1 ordinary rounds
301 for(r
= ROUNDS
-1; r
> 0; r
--) {
302 KeyAddition(a
,rk
[r
],BC
);
304 Substitution(a
,Si
,BC
);
308 /* End with the extra key addition
311 KeyAddition(a
,rk
[0],BC
);
318 int rijndaelDecryptRound (word8 a
[4][MAXBC
], int keyBits
, int blockBits
,
319 word8 rk
[MAXROUNDS
+1][4][MAXBC
], int rounds
)
320 /* Decrypt only a certain number of rounds.
321 * Only used in the Intermediate Value Known Answer Test.
322 * Operations rearranged such that the intermediate values
323 * of decryption correspond with the intermediate values
330 case 128: BC
= 4; break;
331 case 192: BC
= 6; break;
332 case 256: BC
= 8; break;
333 default : return (-2);
336 switch (keyBits
>= blockBits
? keyBits
: blockBits
) {
337 case 128: ROUNDS
= 10; break;
338 case 192: ROUNDS
= 12; break;
339 case 256: ROUNDS
= 14; break;
340 default : return (-3); /* this cannot happen */
344 /* make number of rounds sane */
345 if (rounds
> ROUNDS
) rounds
= ROUNDS
;
347 /* First the special round:
348 * without InvMixColumn
349 * with extra KeyAddition
351 KeyAddition(a
,rk
[ROUNDS
],BC
);
352 Substitution(a
,Si
,BC
);
355 /* ROUNDS-1 ordinary rounds
357 for(r
= ROUNDS
-1; r
> rounds
; r
--) {
358 KeyAddition(a
,rk
[r
],BC
);
360 Substitution(a
,Si
,BC
);
365 /* End with the extra key addition
367 KeyAddition(a
,rk
[0],BC
);
373 #endif /* __APPLE__ */