Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / freebl / rijndael.c
blobfca37e80bf1811851ff32ef529934fc9d800811c
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
36 /* $Id: rijndael.c,v 1.20 2005/08/09 03:09:38 nelsonb%netscape.com Exp $ */
38 #include "prinit.h"
39 #include "prerr.h"
40 #include "secerr.h"
42 #include "prtypes.h"
43 #include "blapi.h"
44 #include "rijndael.h"
47 * There are currently five ways to build this code, varying in performance
48 * and code size.
50 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab
51 * RIJNDAEL_GENERATE_TABLES Generate tables on first
52 * encryption/decryption, then store them;
53 * use the function gfm
54 * RIJNDAEL_GENERATE_TABLES_MACRO Same as above, but use macros to do
55 * the generation
56 * RIJNDAEL_GENERATE_VALUES Do not store tables, generate the table
57 * values "on-the-fly", using gfm
58 * RIJNDAEL_GENERATE_VALUES_MACRO Same as above, but use macros
60 * The default is RIJNDAEL_INCLUDE_TABLES.
64 * When building RIJNDAEL_INCLUDE_TABLES, includes S**-1, Rcon, T[0..4],
65 * T**-1[0..4], IMXC[0..4]
66 * When building anything else, includes S, S**-1, Rcon
68 #include "rijndael32.tab"
70 #if defined(RIJNDAEL_INCLUDE_TABLES)
72 * RIJNDAEL_INCLUDE_TABLES
74 #define T0(i) _T0[i]
75 #define T1(i) _T1[i]
76 #define T2(i) _T2[i]
77 #define T3(i) _T3[i]
78 #define TInv0(i) _TInv0[i]
79 #define TInv1(i) _TInv1[i]
80 #define TInv2(i) _TInv2[i]
81 #define TInv3(i) _TInv3[i]
82 #define IMXC0(b) _IMXC0[b]
83 #define IMXC1(b) _IMXC1[b]
84 #define IMXC2(b) _IMXC2[b]
85 #define IMXC3(b) _IMXC3[b]
86 /* The S-box can be recovered from the T-tables */
87 #ifdef IS_LITTLE_ENDIAN
88 #define SBOX(b) ((PRUint8)_T3[b])
89 #else
90 #define SBOX(b) ((PRUint8)_T1[b])
91 #endif
92 #define SINV(b) (_SInv[b])
94 #else /* not RIJNDAEL_INCLUDE_TABLES */
97 * Code for generating T-table values.
100 #ifdef IS_LITTLE_ENDIAN
101 #define WORD4(b0, b1, b2, b3) \
102 (((b3) << 24) | ((b2) << 16) | ((b1) << 8) | (b0))
103 #else
104 #define WORD4(b0, b1, b2, b3) \
105 (((b0) << 24) | ((b1) << 16) | ((b2) << 8) | (b3))
106 #endif
109 * Define the S and S**-1 tables (both have been stored)
111 #define SBOX(b) (_S[b])
112 #define SINV(b) (_SInv[b])
115 * The function xtime, used for Galois field multiplication
117 #define XTIME(a) \
118 ((a & 0x80) ? ((a << 1) ^ 0x1b) : (a << 1))
120 /* Choose GFM method (macros or function) */
121 #if defined(RIJNDAEL_GENERATE_TABLES_MACRO) || \
122 defined(RIJNDAEL_GENERATE_VALUES_MACRO)
125 * Galois field GF(2**8) multipliers, in macro form
127 #define GFM01(a) \
128 (a) /* a * 01 = a, the identity */
129 #define GFM02(a) \
130 (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
131 #define GFM04(a) \
132 (GFM02(GFM02(a))) /* a * 04 = xtime**2(a) */
133 #define GFM08(a) \
134 (GFM02(GFM04(a))) /* a * 08 = xtime**3(a) */
135 #define GFM03(a) \
136 (GFM01(a) ^ GFM02(a)) /* a * 03 = a * (01 + 02) */
137 #define GFM09(a) \
138 (GFM01(a) ^ GFM08(a)) /* a * 09 = a * (01 + 08) */
139 #define GFM0B(a) \
140 (GFM01(a) ^ GFM02(a) ^ GFM08(a)) /* a * 0B = a * (01 + 02 + 08) */
141 #define GFM0D(a) \
142 (GFM01(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0D = a * (01 + 04 + 08) */
143 #define GFM0E(a) \
144 (GFM02(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0E = a * (02 + 04 + 08) */
146 #else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_VALUES */
148 /* GF_MULTIPLY
150 * multiply two bytes represented in GF(2**8), mod (x**4 + 1)
152 PRUint8 gfm(PRUint8 a, PRUint8 b)
154 PRUint8 res = 0;
155 while (b > 0) {
156 res = (b & 0x01) ? res ^ a : res;
157 a = XTIME(a);
158 b >>= 1;
160 return res;
163 #define GFM01(a) \
164 (a) /* a * 01 = a, the identity */
165 #define GFM02(a) \
166 (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
167 #define GFM03(a) \
168 (gfm(a, 0x03)) /* a * 03 */
169 #define GFM09(a) \
170 (gfm(a, 0x09)) /* a * 09 */
171 #define GFM0B(a) \
172 (gfm(a, 0x0B)) /* a * 0B */
173 #define GFM0D(a) \
174 (gfm(a, 0x0D)) /* a * 0D */
175 #define GFM0E(a) \
176 (gfm(a, 0x0E)) /* a * 0E */
178 #endif /* choosing GFM function */
181 * The T-tables
183 #define G_T0(i) \
184 ( WORD4( GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)) ) )
185 #define G_T1(i) \
186 ( WORD4( GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)) ) )
187 #define G_T2(i) \
188 ( WORD4( GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)) ) )
189 #define G_T3(i) \
190 ( WORD4( GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)) ) )
193 * The inverse T-tables
195 #define G_TInv0(i) \
196 ( WORD4( GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)) ) )
197 #define G_TInv1(i) \
198 ( WORD4( GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)) ) )
199 #define G_TInv2(i) \
200 ( WORD4( GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)) ) )
201 #define G_TInv3(i) \
202 ( WORD4( GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)) ) )
205 * The inverse mix column tables
207 #define G_IMXC0(i) \
208 ( WORD4( GFM0E(i), GFM09(i), GFM0D(i), GFM0B(i) ) )
209 #define G_IMXC1(i) \
210 ( WORD4( GFM0B(i), GFM0E(i), GFM09(i), GFM0D(i) ) )
211 #define G_IMXC2(i) \
212 ( WORD4( GFM0D(i), GFM0B(i), GFM0E(i), GFM09(i) ) )
213 #define G_IMXC3(i) \
214 ( WORD4( GFM09(i), GFM0D(i), GFM0B(i), GFM0E(i) ) )
216 /* Now choose the T-table indexing method */
217 #if defined(RIJNDAEL_GENERATE_VALUES)
218 /* generate values for the tables with a function*/
219 static PRUint32 gen_TInvXi(PRUint8 tx, PRUint8 i)
221 PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E;
222 si01 = SINV(i);
223 si02 = XTIME(si01);
224 si04 = XTIME(si02);
225 si08 = XTIME(si04);
226 si03 = si02 ^ si01;
227 si09 = si08 ^ si01;
228 si0B = si08 ^ si03;
229 si0D = si09 ^ si04;
230 si0E = si08 ^ si04 ^ si02;
231 switch (tx) {
232 case 0:
233 return WORD4(si0E, si09, si0D, si0B);
234 case 1:
235 return WORD4(si0B, si0E, si09, si0D);
236 case 2:
237 return WORD4(si0D, si0B, si0E, si09);
238 case 3:
239 return WORD4(si09, si0D, si0B, si0E);
241 return -1;
243 #define T0(i) G_T0(i)
244 #define T1(i) G_T1(i)
245 #define T2(i) G_T2(i)
246 #define T3(i) G_T3(i)
247 #define TInv0(i) gen_TInvXi(0, i)
248 #define TInv1(i) gen_TInvXi(1, i)
249 #define TInv2(i) gen_TInvXi(2, i)
250 #define TInv3(i) gen_TInvXi(3, i)
251 #define IMXC0(b) G_IMXC0(b)
252 #define IMXC1(b) G_IMXC1(b)
253 #define IMXC2(b) G_IMXC2(b)
254 #define IMXC3(b) G_IMXC3(b)
255 #elif defined(RIJNDAEL_GENERATE_VALUES_MACRO)
256 /* generate values for the tables with macros */
257 #define T0(i) G_T0(i)
258 #define T1(i) G_T1(i)
259 #define T2(i) G_T2(i)
260 #define T3(i) G_T3(i)
261 #define TInv0(i) G_TInv0(i)
262 #define TInv1(i) G_TInv1(i)
263 #define TInv2(i) G_TInv2(i)
264 #define TInv3(i) G_TInv3(i)
265 #define IMXC0(b) G_IMXC0(b)
266 #define IMXC1(b) G_IMXC1(b)
267 #define IMXC2(b) G_IMXC2(b)
268 #define IMXC3(b) G_IMXC3(b)
269 #else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_TABLES_MACRO */
270 /* Generate T and T**-1 table values and store, then index */
271 /* The inverse mix column tables are still generated */
272 #define T0(i) rijndaelTables->T0[i]
273 #define T1(i) rijndaelTables->T1[i]
274 #define T2(i) rijndaelTables->T2[i]
275 #define T3(i) rijndaelTables->T3[i]
276 #define TInv0(i) rijndaelTables->TInv0[i]
277 #define TInv1(i) rijndaelTables->TInv1[i]
278 #define TInv2(i) rijndaelTables->TInv2[i]
279 #define TInv3(i) rijndaelTables->TInv3[i]
280 #define IMXC0(b) G_IMXC0(b)
281 #define IMXC1(b) G_IMXC1(b)
282 #define IMXC2(b) G_IMXC2(b)
283 #define IMXC3(b) G_IMXC3(b)
284 #endif /* choose T-table indexing method */
286 #endif /* not RIJNDAEL_INCLUDE_TABLES */
288 #if defined(RIJNDAEL_GENERATE_TABLES) || \
289 defined(RIJNDAEL_GENERATE_TABLES_MACRO)
291 /* Code to generate and store the tables */
293 struct rijndael_tables_str {
294 PRUint32 T0[256];
295 PRUint32 T1[256];
296 PRUint32 T2[256];
297 PRUint32 T3[256];
298 PRUint32 TInv0[256];
299 PRUint32 TInv1[256];
300 PRUint32 TInv2[256];
301 PRUint32 TInv3[256];
304 static struct rijndael_tables_str *rijndaelTables = NULL;
305 static PRCallOnceType coRTInit = { 0, 0, 0 };
306 static PRStatus
307 init_rijndael_tables(void)
309 PRUint32 i;
310 PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E;
311 struct rijndael_tables_str *rts;
312 rts = (struct rijndael_tables_str *)
313 PORT_Alloc(sizeof(struct rijndael_tables_str));
314 if (!rts) return PR_FAILURE;
315 for (i=0; i<256; i++) {
316 /* The forward values */
317 si01 = SBOX(i);
318 si02 = XTIME(si01);
319 si03 = si02 ^ si01;
320 rts->T0[i] = WORD4(si02, si01, si01, si03);
321 rts->T1[i] = WORD4(si03, si02, si01, si01);
322 rts->T2[i] = WORD4(si01, si03, si02, si01);
323 rts->T3[i] = WORD4(si01, si01, si03, si02);
324 /* The inverse values */
325 si01 = SINV(i);
326 si02 = XTIME(si01);
327 si04 = XTIME(si02);
328 si08 = XTIME(si04);
329 si03 = si02 ^ si01;
330 si09 = si08 ^ si01;
331 si0B = si08 ^ si03;
332 si0D = si09 ^ si04;
333 si0E = si08 ^ si04 ^ si02;
334 rts->TInv0[i] = WORD4(si0E, si09, si0D, si0B);
335 rts->TInv1[i] = WORD4(si0B, si0E, si09, si0D);
336 rts->TInv2[i] = WORD4(si0D, si0B, si0E, si09);
337 rts->TInv3[i] = WORD4(si09, si0D, si0B, si0E);
339 /* wait until all the values are in to set */
340 rijndaelTables = rts;
341 return PR_SUCCESS;
344 #endif /* code to generate tables */
346 /**************************************************************************
348 * Stuff related to the Rijndael key schedule
350 *************************************************************************/
352 #define SUBBYTE(w) \
353 ((SBOX((w >> 24) & 0xff) << 24) | \
354 (SBOX((w >> 16) & 0xff) << 16) | \
355 (SBOX((w >> 8) & 0xff) << 8) | \
356 (SBOX((w ) & 0xff) ))
358 #ifdef IS_LITTLE_ENDIAN
359 #define ROTBYTE(b) \
360 ((b >> 8) | (b << 24))
361 #else
362 #define ROTBYTE(b) \
363 ((b << 8) | (b >> 24))
364 #endif
366 /* rijndael_key_expansion7
368 * Generate the expanded key from the key input by the user.
369 * XXX
370 * Nk == 7 (224 key bits) is a weird case. Since Nk > 6, an added SubByte
371 * transformation is done periodically. The period is every 4 bytes, and
372 * since 7%4 != 0 this happens at different times for each key word (unlike
373 * Nk == 8 where it happens twice in every key word, in the same positions).
374 * For now, I'm implementing this case "dumbly", w/o any unrolling.
376 static SECStatus
377 rijndael_key_expansion7(AESContext *cx, const unsigned char *key, unsigned int Nk)
379 unsigned int i;
380 PRUint32 *W;
381 PRUint32 *pW;
382 PRUint32 tmp;
383 W = cx->expandedKey;
384 /* 1. the first Nk words contain the cipher key */
385 memcpy(W, key, Nk * 4);
386 i = Nk;
387 /* 2. loop until full expanded key is obtained */
388 pW = W + i - 1;
389 for (; i < cx->Nb * (cx->Nr + 1); ++i) {
390 tmp = *pW++;
391 if (i % Nk == 0)
392 tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
393 else if (i % Nk == 4)
394 tmp = SUBBYTE(tmp);
395 *pW = W[i - Nk] ^ tmp;
397 return SECSuccess;
400 /* rijndael_key_expansion
402 * Generate the expanded key from the key input by the user.
404 static SECStatus
405 rijndael_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
407 unsigned int i;
408 PRUint32 *W;
409 PRUint32 *pW;
410 PRUint32 tmp;
411 unsigned int round_key_words = cx->Nb * (cx->Nr + 1);
412 if (Nk == 7)
413 return rijndael_key_expansion7(cx, key, Nk);
414 W = cx->expandedKey;
415 /* The first Nk words contain the input cipher key */
416 memcpy(W, key, Nk * 4);
417 i = Nk;
418 pW = W + i - 1;
419 /* Loop over all sets of Nk words, except the last */
420 while (i < round_key_words - Nk) {
421 tmp = *pW++;
422 tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
423 *pW = W[i++ - Nk] ^ tmp;
424 tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
425 tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
426 tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
427 if (Nk == 4)
428 continue;
429 switch (Nk) {
430 case 8: tmp = *pW++; tmp = SUBBYTE(tmp); *pW = W[i++ - Nk] ^ tmp;
431 case 7: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
432 case 6: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
433 case 5: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
436 /* Generate the last word */
437 tmp = *pW++;
438 tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
439 *pW = W[i++ - Nk] ^ tmp;
440 /* There may be overflow here, if Nk % (Nb * (Nr + 1)) > 0. However,
441 * since the above loop generated all but the last Nk key words, there
442 * is no more need for the SubByte transformation.
444 if (Nk < 8) {
445 for (; i < round_key_words; ++i) {
446 tmp = *pW++;
447 *pW = W[i - Nk] ^ tmp;
449 } else {
450 /* except in the case when Nk == 8. Then one more SubByte may have
451 * to be performed, at i % Nk == 4.
453 for (; i < round_key_words; ++i) {
454 tmp = *pW++;
455 if (i % Nk == 4)
456 tmp = SUBBYTE(tmp);
457 *pW = W[i - Nk] ^ tmp;
460 return SECSuccess;
463 /* rijndael_invkey_expansion
465 * Generate the expanded key for the inverse cipher from the key input by
466 * the user.
468 static SECStatus
469 rijndael_invkey_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
471 unsigned int r;
472 PRUint32 *roundkeyw;
473 PRUint8 *b;
474 int Nb = cx->Nb;
475 /* begins like usual key expansion ... */
476 if (rijndael_key_expansion(cx, key, Nk) != SECSuccess)
477 return SECFailure;
478 /* ... but has the additional step of InvMixColumn,
479 * excepting the first and last round keys.
481 roundkeyw = cx->expandedKey + cx->Nb;
482 for (r=1; r<cx->Nr; ++r) {
483 /* each key word, roundkeyw, represents a column in the key
484 * matrix. Each column is multiplied by the InvMixColumn matrix.
485 * [ 0E 0B 0D 09 ] [ b0 ]
486 * [ 09 0E 0B 0D ] * [ b1 ]
487 * [ 0D 09 0E 0B ] [ b2 ]
488 * [ 0B 0D 09 0E ] [ b3 ]
490 b = (PRUint8 *)roundkeyw;
491 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
492 b = (PRUint8 *)roundkeyw;
493 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
494 b = (PRUint8 *)roundkeyw;
495 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
496 b = (PRUint8 *)roundkeyw;
497 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
498 if (Nb <= 4)
499 continue;
500 switch (Nb) {
501 case 8: b = (PRUint8 *)roundkeyw;
502 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
503 IMXC2(b[2]) ^ IMXC3(b[3]);
504 case 7: b = (PRUint8 *)roundkeyw;
505 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
506 IMXC2(b[2]) ^ IMXC3(b[3]);
507 case 6: b = (PRUint8 *)roundkeyw;
508 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
509 IMXC2(b[2]) ^ IMXC3(b[3]);
510 case 5: b = (PRUint8 *)roundkeyw;
511 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
512 IMXC2(b[2]) ^ IMXC3(b[3]);
515 return SECSuccess;
517 /**************************************************************************
519 * Stuff related to Rijndael encryption/decryption, optimized for
520 * a 128-bit blocksize.
522 *************************************************************************/
524 #ifdef IS_LITTLE_ENDIAN
525 #define BYTE0WORD(w) ((w) & 0x000000ff)
526 #define BYTE1WORD(w) ((w) & 0x0000ff00)
527 #define BYTE2WORD(w) ((w) & 0x00ff0000)
528 #define BYTE3WORD(w) ((w) & 0xff000000)
529 #else
530 #define BYTE0WORD(w) ((w) & 0xff000000)
531 #define BYTE1WORD(w) ((w) & 0x00ff0000)
532 #define BYTE2WORD(w) ((w) & 0x0000ff00)
533 #define BYTE3WORD(w) ((w) & 0x000000ff)
534 #endif
536 typedef union {
537 PRUint32 w[4];
538 PRUint8 b[16];
539 } rijndael_state;
541 #define COLUMN_0(state) state.w[0]
542 #define COLUMN_1(state) state.w[1]
543 #define COLUMN_2(state) state.w[2]
544 #define COLUMN_3(state) state.w[3]
546 #define STATE_BYTE(i) state.b[i]
548 static SECStatus
549 rijndael_encryptBlock128(AESContext *cx,
550 unsigned char *output,
551 const unsigned char *input)
553 unsigned int r;
554 PRUint32 *roundkeyw;
555 rijndael_state state;
556 PRUint32 C0, C1, C2, C3;
557 #if defined(_X86_)
558 #define pIn input
559 #define pOut output
560 #else
561 unsigned char *pIn, *pOut;
562 PRUint32 inBuf[4], outBuf[4];
564 if ((ptrdiff_t)input & 0x3) {
565 memcpy(inBuf, input, sizeof inBuf);
566 pIn = (unsigned char *)inBuf;
567 } else {
568 pIn = (unsigned char *)input;
570 if ((ptrdiff_t)output & 0x3) {
571 pOut = (unsigned char *)outBuf;
572 } else {
573 pOut = (unsigned char *)output;
575 #endif
576 roundkeyw = cx->expandedKey;
577 /* Step 1: Add Round Key 0 to initial state */
578 COLUMN_0(state) = *((PRUint32 *)(pIn )) ^ *roundkeyw++;
579 COLUMN_1(state) = *((PRUint32 *)(pIn + 4 )) ^ *roundkeyw++;
580 COLUMN_2(state) = *((PRUint32 *)(pIn + 8 )) ^ *roundkeyw++;
581 COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw++;
582 /* Step 2: Loop over rounds [1..NR-1] */
583 for (r=1; r<cx->Nr; ++r) {
584 /* Do ShiftRow, ByteSub, and MixColumn all at once */
585 C0 = T0(STATE_BYTE(0)) ^
586 T1(STATE_BYTE(5)) ^
587 T2(STATE_BYTE(10)) ^
588 T3(STATE_BYTE(15));
589 C1 = T0(STATE_BYTE(4)) ^
590 T1(STATE_BYTE(9)) ^
591 T2(STATE_BYTE(14)) ^
592 T3(STATE_BYTE(3));
593 C2 = T0(STATE_BYTE(8)) ^
594 T1(STATE_BYTE(13)) ^
595 T2(STATE_BYTE(2)) ^
596 T3(STATE_BYTE(7));
597 C3 = T0(STATE_BYTE(12)) ^
598 T1(STATE_BYTE(1)) ^
599 T2(STATE_BYTE(6)) ^
600 T3(STATE_BYTE(11));
601 /* Round key addition */
602 COLUMN_0(state) = C0 ^ *roundkeyw++;
603 COLUMN_1(state) = C1 ^ *roundkeyw++;
604 COLUMN_2(state) = C2 ^ *roundkeyw++;
605 COLUMN_3(state) = C3 ^ *roundkeyw++;
607 /* Step 3: Do the last round */
608 /* Final round does not employ MixColumn */
609 C0 = ((BYTE0WORD(T2(STATE_BYTE(0)))) |
610 (BYTE1WORD(T3(STATE_BYTE(5)))) |
611 (BYTE2WORD(T0(STATE_BYTE(10)))) |
612 (BYTE3WORD(T1(STATE_BYTE(15))))) ^
613 *roundkeyw++;
614 C1 = ((BYTE0WORD(T2(STATE_BYTE(4)))) |
615 (BYTE1WORD(T3(STATE_BYTE(9)))) |
616 (BYTE2WORD(T0(STATE_BYTE(14)))) |
617 (BYTE3WORD(T1(STATE_BYTE(3))))) ^
618 *roundkeyw++;
619 C2 = ((BYTE0WORD(T2(STATE_BYTE(8)))) |
620 (BYTE1WORD(T3(STATE_BYTE(13)))) |
621 (BYTE2WORD(T0(STATE_BYTE(2)))) |
622 (BYTE3WORD(T1(STATE_BYTE(7))))) ^
623 *roundkeyw++;
624 C3 = ((BYTE0WORD(T2(STATE_BYTE(12)))) |
625 (BYTE1WORD(T3(STATE_BYTE(1)))) |
626 (BYTE2WORD(T0(STATE_BYTE(6)))) |
627 (BYTE3WORD(T1(STATE_BYTE(11))))) ^
628 *roundkeyw++;
629 *((PRUint32 *) pOut ) = C0;
630 *((PRUint32 *)(pOut + 4)) = C1;
631 *((PRUint32 *)(pOut + 8)) = C2;
632 *((PRUint32 *)(pOut + 12)) = C3;
633 #if defined(_X86_)
634 #undef pIn
635 #undef pOut
636 #else
637 if ((ptrdiff_t)output & 0x3) {
638 memcpy(output, outBuf, sizeof outBuf);
640 #endif
641 return SECSuccess;
644 static SECStatus
645 rijndael_decryptBlock128(AESContext *cx,
646 unsigned char *output,
647 const unsigned char *input)
649 int r;
650 PRUint32 *roundkeyw;
651 rijndael_state state;
652 PRUint32 C0, C1, C2, C3;
653 #if defined(_X86_)
654 #define pIn input
655 #define pOut output
656 #else
657 unsigned char *pIn, *pOut;
658 PRUint32 inBuf[4], outBuf[4];
660 if ((ptrdiff_t)input & 0x3) {
661 memcpy(inBuf, input, sizeof inBuf);
662 pIn = (unsigned char *)inBuf;
663 } else {
664 pIn = (unsigned char *)input;
666 if ((ptrdiff_t)output & 0x3) {
667 pOut = (unsigned char *)outBuf;
668 } else {
669 pOut = (unsigned char *)output;
671 #endif
672 roundkeyw = cx->expandedKey + cx->Nb * cx->Nr + 3;
673 /* reverse the final key addition */
674 COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw--;
675 COLUMN_2(state) = *((PRUint32 *)(pIn + 8)) ^ *roundkeyw--;
676 COLUMN_1(state) = *((PRUint32 *)(pIn + 4)) ^ *roundkeyw--;
677 COLUMN_0(state) = *((PRUint32 *)(pIn )) ^ *roundkeyw--;
678 /* Loop over rounds in reverse [NR..1] */
679 for (r=cx->Nr; r>1; --r) {
680 /* Invert the (InvByteSub*InvMixColumn)(InvShiftRow(state)) */
681 C0 = TInv0(STATE_BYTE(0)) ^
682 TInv1(STATE_BYTE(13)) ^
683 TInv2(STATE_BYTE(10)) ^
684 TInv3(STATE_BYTE(7));
685 C1 = TInv0(STATE_BYTE(4)) ^
686 TInv1(STATE_BYTE(1)) ^
687 TInv2(STATE_BYTE(14)) ^
688 TInv3(STATE_BYTE(11));
689 C2 = TInv0(STATE_BYTE(8)) ^
690 TInv1(STATE_BYTE(5)) ^
691 TInv2(STATE_BYTE(2)) ^
692 TInv3(STATE_BYTE(15));
693 C3 = TInv0(STATE_BYTE(12)) ^
694 TInv1(STATE_BYTE(9)) ^
695 TInv2(STATE_BYTE(6)) ^
696 TInv3(STATE_BYTE(3));
697 /* Invert the key addition step */
698 COLUMN_3(state) = C3 ^ *roundkeyw--;
699 COLUMN_2(state) = C2 ^ *roundkeyw--;
700 COLUMN_1(state) = C1 ^ *roundkeyw--;
701 COLUMN_0(state) = C0 ^ *roundkeyw--;
703 /* inverse sub */
704 pOut[ 0] = SINV(STATE_BYTE( 0));
705 pOut[ 1] = SINV(STATE_BYTE(13));
706 pOut[ 2] = SINV(STATE_BYTE(10));
707 pOut[ 3] = SINV(STATE_BYTE( 7));
708 pOut[ 4] = SINV(STATE_BYTE( 4));
709 pOut[ 5] = SINV(STATE_BYTE( 1));
710 pOut[ 6] = SINV(STATE_BYTE(14));
711 pOut[ 7] = SINV(STATE_BYTE(11));
712 pOut[ 8] = SINV(STATE_BYTE( 8));
713 pOut[ 9] = SINV(STATE_BYTE( 5));
714 pOut[10] = SINV(STATE_BYTE( 2));
715 pOut[11] = SINV(STATE_BYTE(15));
716 pOut[12] = SINV(STATE_BYTE(12));
717 pOut[13] = SINV(STATE_BYTE( 9));
718 pOut[14] = SINV(STATE_BYTE( 6));
719 pOut[15] = SINV(STATE_BYTE( 3));
720 /* final key addition */
721 *((PRUint32 *)(pOut + 12)) ^= *roundkeyw--;
722 *((PRUint32 *)(pOut + 8)) ^= *roundkeyw--;
723 *((PRUint32 *)(pOut + 4)) ^= *roundkeyw--;
724 *((PRUint32 *) pOut ) ^= *roundkeyw--;
725 #if defined(_X86_)
726 #undef pIn
727 #undef pOut
728 #else
729 if ((ptrdiff_t)output & 0x3) {
730 memcpy(output, outBuf, sizeof outBuf);
732 #endif
733 return SECSuccess;
736 /**************************************************************************
738 * Stuff related to general Rijndael encryption/decryption, for blocksizes
739 * greater than 128 bits.
741 * XXX This code is currently untested! So far, AES specs have only been
742 * released for 128 bit blocksizes. This will be tested, but for now
743 * only the code above has been tested using known values.
745 *************************************************************************/
747 #define COLUMN(array, j) *((PRUint32 *)(array + j))
749 SECStatus
750 rijndael_encryptBlock(AESContext *cx,
751 unsigned char *output,
752 const unsigned char *input)
754 return SECFailure;
755 #ifdef rijndael_large_blocks_fixed
756 unsigned int j, r, Nb;
757 unsigned int c2=0, c3=0;
758 PRUint32 *roundkeyw;
759 PRUint8 clone[RIJNDAEL_MAX_STATE_SIZE];
760 Nb = cx->Nb;
761 roundkeyw = cx->expandedKey;
762 /* Step 1: Add Round Key 0 to initial state */
763 for (j=0; j<4*Nb; j+=4) {
764 COLUMN(clone, j) = COLUMN(input, j) ^ *roundkeyw++;
766 /* Step 2: Loop over rounds [1..NR-1] */
767 for (r=1; r<cx->Nr; ++r) {
768 for (j=0; j<Nb; ++j) {
769 COLUMN(output, j) = T0(STATE_BYTE(4* j )) ^
770 T1(STATE_BYTE(4*((j+ 1)%Nb)+1)) ^
771 T2(STATE_BYTE(4*((j+c2)%Nb)+2)) ^
772 T3(STATE_BYTE(4*((j+c3)%Nb)+3));
774 for (j=0; j<4*Nb; j+=4) {
775 COLUMN(clone, j) = COLUMN(output, j) ^ *roundkeyw++;
778 /* Step 3: Do the last round */
779 /* Final round does not employ MixColumn */
780 for (j=0; j<Nb; ++j) {
781 COLUMN(output, j) = ((BYTE0WORD(T2(STATE_BYTE(4* j )))) |
782 (BYTE1WORD(T3(STATE_BYTE(4*(j+ 1)%Nb)+1))) |
783 (BYTE2WORD(T0(STATE_BYTE(4*(j+c2)%Nb)+2))) |
784 (BYTE3WORD(T1(STATE_BYTE(4*(j+c3)%Nb)+3)))) ^
785 *roundkeyw++;
787 return SECSuccess;
788 #endif
791 SECStatus
792 rijndael_decryptBlock(AESContext *cx,
793 unsigned char *output,
794 const unsigned char *input)
796 return SECFailure;
797 #ifdef rijndael_large_blocks_fixed
798 int j, r, Nb;
799 int c2=0, c3=0;
800 PRUint32 *roundkeyw;
801 PRUint8 clone[RIJNDAEL_MAX_STATE_SIZE];
802 Nb = cx->Nb;
803 roundkeyw = cx->expandedKey + cx->Nb * cx->Nr + 3;
804 /* reverse key addition */
805 for (j=4*Nb; j>=0; j-=4) {
806 COLUMN(clone, j) = COLUMN(input, j) ^ *roundkeyw--;
808 /* Loop over rounds in reverse [NR..1] */
809 for (r=cx->Nr; r>1; --r) {
810 /* Invert the (InvByteSub*InvMixColumn)(InvShiftRow(state)) */
811 for (j=0; j<Nb; ++j) {
812 COLUMN(output, 4*j) = TInv0(STATE_BYTE(4* j )) ^
813 TInv1(STATE_BYTE(4*(j+Nb- 1)%Nb)+1) ^
814 TInv2(STATE_BYTE(4*(j+Nb-c2)%Nb)+2) ^
815 TInv3(STATE_BYTE(4*(j+Nb-c3)%Nb)+3);
817 /* Invert the key addition step */
818 for (j=4*Nb; j>=0; j-=4) {
819 COLUMN(clone, j) = COLUMN(output, j) ^ *roundkeyw--;
822 /* inverse sub */
823 for (j=0; j<4*Nb; ++j) {
824 output[j] = SINV(clone[j]);
826 /* final key addition */
827 for (j=4*Nb; j>=0; j-=4) {
828 COLUMN(output, j) ^= *roundkeyw--;
830 return SECSuccess;
831 #endif
834 /**************************************************************************
836 * Rijndael modes of operation (ECB and CBC)
838 *************************************************************************/
840 static SECStatus
841 rijndael_encryptECB(AESContext *cx, unsigned char *output,
842 unsigned int *outputLen, unsigned int maxOutputLen,
843 const unsigned char *input, unsigned int inputLen,
844 unsigned int blocksize)
846 SECStatus rv;
847 AESBlockFunc *encryptor;
848 encryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE)
849 ? &rijndael_encryptBlock128
850 : &rijndael_encryptBlock;
851 while (inputLen > 0) {
852 rv = (*encryptor)(cx, output, input);
853 if (rv != SECSuccess)
854 return rv;
855 output += blocksize;
856 input += blocksize;
857 inputLen -= blocksize;
859 return SECSuccess;
862 static SECStatus
863 rijndael_encryptCBC(AESContext *cx, unsigned char *output,
864 unsigned int *outputLen, unsigned int maxOutputLen,
865 const unsigned char *input, unsigned int inputLen,
866 unsigned int blocksize)
868 unsigned int j;
869 SECStatus rv;
870 AESBlockFunc *encryptor;
871 unsigned char *lastblock;
872 unsigned char inblock[RIJNDAEL_MAX_STATE_SIZE * 8];
874 if (!inputLen)
875 return SECSuccess;
876 lastblock = cx->iv;
877 encryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE)
878 ? &rijndael_encryptBlock128
879 : &rijndael_encryptBlock;
880 while (inputLen > 0) {
881 /* XOR with the last block (IV if first block) */
882 for (j=0; j<blocksize; ++j)
883 inblock[j] = input[j] ^ lastblock[j];
884 /* encrypt */
885 rv = (*encryptor)(cx, output, inblock);
886 if (rv != SECSuccess)
887 return rv;
888 /* move to the next block */
889 lastblock = output;
890 output += blocksize;
891 input += blocksize;
892 inputLen -= blocksize;
894 memcpy(cx->iv, lastblock, blocksize);
895 return SECSuccess;
898 static SECStatus
899 rijndael_decryptECB(AESContext *cx, unsigned char *output,
900 unsigned int *outputLen, unsigned int maxOutputLen,
901 const unsigned char *input, unsigned int inputLen,
902 unsigned int blocksize)
904 SECStatus rv;
905 AESBlockFunc *decryptor;
906 decryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE)
907 ? &rijndael_decryptBlock128
908 : &rijndael_decryptBlock;
909 while (inputLen > 0) {
910 rv = (*decryptor)(cx, output, input);
911 if (rv != SECSuccess)
912 return rv;
913 output += blocksize;
914 input += blocksize;
915 inputLen -= blocksize;
917 return SECSuccess;
920 static SECStatus
921 rijndael_decryptCBC(AESContext *cx, unsigned char *output,
922 unsigned int *outputLen, unsigned int maxOutputLen,
923 const unsigned char *input, unsigned int inputLen,
924 unsigned int blocksize)
926 SECStatus rv;
927 AESBlockFunc *decryptor;
928 const unsigned char *in;
929 unsigned char *out;
930 unsigned int j;
931 unsigned char newIV[RIJNDAEL_MAX_BLOCKSIZE];
933 if (!inputLen)
934 return SECSuccess;
935 PORT_Assert(output - input >= 0 || input - output >= (int)inputLen );
936 decryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE)
937 ? &rijndael_decryptBlock128
938 : &rijndael_decryptBlock;
939 in = input + (inputLen - blocksize);
940 memcpy(newIV, in, blocksize);
941 out = output + (inputLen - blocksize);
942 while (inputLen > blocksize) {
943 rv = (*decryptor)(cx, out, in);
944 if (rv != SECSuccess)
945 return rv;
946 for (j=0; j<blocksize; ++j)
947 out[j] ^= in[(int)(j - blocksize)];
948 out -= blocksize;
949 in -= blocksize;
950 inputLen -= blocksize;
952 if (in == input) {
953 rv = (*decryptor)(cx, out, in);
954 if (rv != SECSuccess)
955 return rv;
956 for (j=0; j<blocksize; ++j)
957 out[j] ^= cx->iv[j];
959 memcpy(cx->iv, newIV, blocksize);
960 return SECSuccess;
963 /************************************************************************
965 * BLAPI Interface functions
967 * The following functions implement the encryption routines defined in
968 * BLAPI for the AES cipher, Rijndael.
970 ***********************************************************************/
972 AESContext * AES_AllocateContext(void)
974 return PORT_ZNew(AESContext);
977 SECStatus
978 AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
979 const unsigned char *iv, int mode, unsigned int encrypt,
980 unsigned int blocksize)
982 unsigned int Nk;
983 /* According to Rijndael AES Proposal, section 12.1, block and key
984 * lengths between 128 and 256 bits are supported, as long as the
985 * length in bytes is divisible by 4.
987 if (key == NULL ||
988 keysize < RIJNDAEL_MIN_BLOCKSIZE ||
989 keysize > RIJNDAEL_MAX_BLOCKSIZE ||
990 keysize % 4 != 0 ||
991 blocksize < RIJNDAEL_MIN_BLOCKSIZE ||
992 blocksize > RIJNDAEL_MAX_BLOCKSIZE ||
993 blocksize % 4 != 0) {
994 PORT_SetError(SEC_ERROR_INVALID_ARGS);
995 return SECFailure;
997 if (mode != NSS_AES && mode != NSS_AES_CBC) {
998 PORT_SetError(SEC_ERROR_INVALID_ARGS);
999 return SECFailure;
1001 if (mode == NSS_AES_CBC && iv == NULL) {
1002 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1003 return SECFailure;
1005 if (!cx) {
1006 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1007 return SECFailure;
1009 /* Nb = (block size in bits) / 32 */
1010 cx->Nb = blocksize / 4;
1011 /* Nk = (key size in bits) / 32 */
1012 Nk = keysize / 4;
1013 /* Obtain number of rounds from "table" */
1014 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb);
1015 /* copy in the iv, if neccessary */
1016 if (mode == NSS_AES_CBC) {
1017 memcpy(cx->iv, iv, blocksize);
1018 cx->worker = (encrypt) ? &rijndael_encryptCBC : &rijndael_decryptCBC;
1019 } else {
1020 cx->worker = (encrypt) ? &rijndael_encryptECB : &rijndael_decryptECB;
1022 PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE);
1023 if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) {
1024 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1025 goto cleanup;
1027 /* Generate expanded key */
1028 if (encrypt) {
1029 if (rijndael_key_expansion(cx, key, Nk) != SECSuccess)
1030 goto cleanup;
1031 } else {
1032 if (rijndael_invkey_expansion(cx, key, Nk) != SECSuccess)
1033 goto cleanup;
1035 return SECSuccess;
1036 cleanup:
1037 return SECFailure;
1041 /* AES_CreateContext
1043 * create a new context for Rijndael operations
1045 AESContext *
1046 AES_CreateContext(const unsigned char *key, const unsigned char *iv,
1047 int mode, int encrypt,
1048 unsigned int keysize, unsigned int blocksize)
1050 AESContext *cx = AES_AllocateContext();
1051 if (cx) {
1052 SECStatus rv = AES_InitContext(cx, key, keysize, iv, mode, encrypt,
1053 blocksize);
1054 if (rv != SECSuccess) {
1055 AES_DestroyContext(cx, PR_TRUE);
1056 cx = NULL;
1059 return cx;
1063 * AES_DestroyContext
1065 * Zero an AES cipher context. If freeit is true, also free the pointer
1066 * to the context.
1068 void
1069 AES_DestroyContext(AESContext *cx, PRBool freeit)
1071 /* memset(cx, 0, sizeof *cx); */
1072 if (freeit)
1073 PORT_Free(cx);
1077 * AES_Encrypt
1079 * Encrypt an arbitrary-length buffer. The output buffer must already be
1080 * allocated to at least inputLen.
1082 SECStatus
1083 AES_Encrypt(AESContext *cx, unsigned char *output,
1084 unsigned int *outputLen, unsigned int maxOutputLen,
1085 const unsigned char *input, unsigned int inputLen)
1087 int blocksize;
1088 /* Check args */
1089 if (cx == NULL || output == NULL || input == NULL) {
1090 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1091 return SECFailure;
1093 blocksize = 4 * cx->Nb;
1094 if (inputLen % blocksize != 0) {
1095 PORT_SetError(SEC_ERROR_INPUT_LEN);
1096 return SECFailure;
1098 if (maxOutputLen < inputLen) {
1099 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1100 return SECFailure;
1102 *outputLen = inputLen;
1103 #if defined(RIJNDAEL_GENERATE_TABLES) || \
1104 defined(RIJNDAEL_GENERATE_TABLES_MACRO)
1105 if (rijndaelTables == NULL) {
1106 if (PR_CallOnce(&coRTInit, init_rijndael_tables)
1107 != PR_SUCCESS) {
1108 return PR_FAILURE;
1111 #endif
1112 return (*cx->worker)(cx, output, outputLen, maxOutputLen,
1113 input, inputLen, blocksize);
1117 * AES_Decrypt
1119 * Decrypt and arbitrary-length buffer. The output buffer must already be
1120 * allocated to at least inputLen.
1122 SECStatus
1123 AES_Decrypt(AESContext *cx, unsigned char *output,
1124 unsigned int *outputLen, unsigned int maxOutputLen,
1125 const unsigned char *input, unsigned int inputLen)
1127 int blocksize;
1128 /* Check args */
1129 if (cx == NULL || output == NULL || input == NULL) {
1130 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1131 return SECFailure;
1133 blocksize = 4 * cx->Nb;
1134 if (inputLen % blocksize != 0) {
1135 PORT_SetError(SEC_ERROR_INPUT_LEN);
1136 return SECFailure;
1138 if (maxOutputLen < inputLen) {
1139 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1140 return SECFailure;
1142 *outputLen = inputLen;
1143 #if defined(RIJNDAEL_GENERATE_TABLES) || \
1144 defined(RIJNDAEL_GENERATE_TABLES_MACRO)
1145 if (rijndaelTables == NULL) {
1146 if (PR_CallOnce(&coRTInit, init_rijndael_tables)
1147 != PR_SUCCESS) {
1148 return PR_FAILURE;
1151 #endif
1152 return (*cx->worker)(cx, output, outputLen, maxOutputLen,
1153 input, inputLen, blocksize);