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
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.
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 $ */
47 * There are currently five ways to build this code, varying in performance
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
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
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])
90 #define SBOX(b) ((PRUint8)_T1[b])
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))
104 #define WORD4(b0, b1, b2, b3) \
105 (((b0) << 24) | ((b1) << 16) | ((b2) << 8) | (b3))
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
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
128 (a) /* a * 01 = a, the identity */
130 (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
132 (GFM02(GFM02(a))) /* a * 04 = xtime**2(a) */
134 (GFM02(GFM04(a))) /* a * 08 = xtime**3(a) */
136 (GFM01(a) ^ GFM02(a)) /* a * 03 = a * (01 + 02) */
138 (GFM01(a) ^ GFM08(a)) /* a * 09 = a * (01 + 08) */
140 (GFM01(a) ^ GFM02(a) ^ GFM08(a)) /* a * 0B = a * (01 + 02 + 08) */
142 (GFM01(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0D = a * (01 + 04 + 08) */
144 (GFM02(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0E = a * (02 + 04 + 08) */
146 #else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_VALUES */
150 * multiply two bytes represented in GF(2**8), mod (x**4 + 1)
152 PRUint8
gfm(PRUint8 a
, PRUint8 b
)
156 res
= (b
& 0x01) ? res
^ a
: res
;
164 (a) /* a * 01 = a, the identity */
166 (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
168 (gfm(a, 0x03)) /* a * 03 */
170 (gfm(a, 0x09)) /* a * 09 */
172 (gfm(a, 0x0B)) /* a * 0B */
174 (gfm(a, 0x0D)) /* a * 0D */
176 (gfm(a, 0x0E)) /* a * 0E */
178 #endif /* choosing GFM function */
184 ( WORD4( GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)) ) )
186 ( WORD4( GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)) ) )
188 ( WORD4( GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)) ) )
190 ( WORD4( GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)) ) )
193 * The inverse T-tables
196 ( WORD4( GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)) ) )
198 ( WORD4( GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)) ) )
200 ( WORD4( GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)) ) )
202 ( WORD4( GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)) ) )
205 * The inverse mix column tables
208 ( WORD4( GFM0E(i), GFM09(i), GFM0D(i), GFM0B(i) ) )
210 ( WORD4( GFM0B(i), GFM0E(i), GFM09(i), GFM0D(i) ) )
212 ( WORD4( GFM0D(i), GFM0B(i), GFM0E(i), GFM09(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
;
230 si0E
= si08
^ si04
^ si02
;
233 return WORD4(si0E
, si09
, si0D
, si0B
);
235 return WORD4(si0B
, si0E
, si09
, si0D
);
237 return WORD4(si0D
, si0B
, si0E
, si09
);
239 return WORD4(si09
, si0D
, si0B
, si0E
);
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
{
304 static struct rijndael_tables_str
*rijndaelTables
= NULL
;
305 static PRCallOnceType coRTInit
= { 0, 0, 0 };
307 init_rijndael_tables(void)
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 */
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 */
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
;
344 #endif /* code to generate tables */
346 /**************************************************************************
348 * Stuff related to the Rijndael key schedule
350 *************************************************************************/
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
360 ((b >> 8) | (b << 24))
363 ((b << 8) | (b >> 24))
366 /* rijndael_key_expansion7
368 * Generate the expanded key from the key input by the user.
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.
377 rijndael_key_expansion7(AESContext
*cx
, const unsigned char *key
, unsigned int Nk
)
384 /* 1. the first Nk words contain the cipher key */
385 memcpy(W
, key
, Nk
* 4);
387 /* 2. loop until full expanded key is obtained */
389 for (; i
< cx
->Nb
* (cx
->Nr
+ 1); ++i
) {
392 tmp
= SUBBYTE(ROTBYTE(tmp
)) ^ Rcon
[i
/ Nk
- 1];
393 else if (i
% Nk
== 4)
395 *pW
= W
[i
- Nk
] ^ tmp
;
400 /* rijndael_key_expansion
402 * Generate the expanded key from the key input by the user.
405 rijndael_key_expansion(AESContext
*cx
, const unsigned char *key
, unsigned int Nk
)
411 unsigned int round_key_words
= cx
->Nb
* (cx
->Nr
+ 1);
413 return rijndael_key_expansion7(cx
, key
, Nk
);
415 /* The first Nk words contain the input cipher key */
416 memcpy(W
, key
, Nk
* 4);
419 /* Loop over all sets of Nk words, except the last */
420 while (i
< round_key_words
- Nk
) {
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
;
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 */
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.
445 for (; i
< round_key_words
; ++i
) {
447 *pW
= W
[i
- Nk
] ^ tmp
;
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
) {
457 *pW
= W
[i
- Nk
] ^ tmp
;
463 /* rijndael_invkey_expansion
465 * Generate the expanded key for the inverse cipher from the key input by
469 rijndael_invkey_expansion(AESContext
*cx
, const unsigned char *key
, unsigned int Nk
)
475 /* begins like usual key expansion ... */
476 if (rijndael_key_expansion(cx
, key
, Nk
) != SECSuccess
)
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]);
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]);
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)
530 #define BYTE0WORD(w) ((w) & 0xff000000)
531 #define BYTE1WORD(w) ((w) & 0x00ff0000)
532 #define BYTE2WORD(w) ((w) & 0x0000ff00)
533 #define BYTE3WORD(w) ((w) & 0x000000ff)
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]
549 rijndael_encryptBlock128(AESContext
*cx
,
550 unsigned char *output
,
551 const unsigned char *input
)
555 rijndael_state state
;
556 PRUint32 C0
, C1
, C2
, C3
;
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
;
568 pIn
= (unsigned char *)input
;
570 if ((ptrdiff_t)output
& 0x3) {
571 pOut
= (unsigned char *)outBuf
;
573 pOut
= (unsigned char *)output
;
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)) ^
589 C1
= T0(STATE_BYTE(4)) ^
593 C2
= T0(STATE_BYTE(8)) ^
597 C3
= T0(STATE_BYTE(12)) ^
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))))) ^
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))))) ^
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))))) ^
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))))) ^
629 *((PRUint32
*) pOut
) = C0
;
630 *((PRUint32
*)(pOut
+ 4)) = C1
;
631 *((PRUint32
*)(pOut
+ 8)) = C2
;
632 *((PRUint32
*)(pOut
+ 12)) = C3
;
637 if ((ptrdiff_t)output
& 0x3) {
638 memcpy(output
, outBuf
, sizeof outBuf
);
645 rijndael_decryptBlock128(AESContext
*cx
,
646 unsigned char *output
,
647 const unsigned char *input
)
651 rijndael_state state
;
652 PRUint32 C0
, C1
, C2
, C3
;
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
;
664 pIn
= (unsigned char *)input
;
666 if ((ptrdiff_t)output
& 0x3) {
667 pOut
= (unsigned char *)outBuf
;
669 pOut
= (unsigned char *)output
;
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
--;
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
--;
729 if ((ptrdiff_t)output
& 0x3) {
730 memcpy(output
, outBuf
, sizeof outBuf
);
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))
750 rijndael_encryptBlock(AESContext
*cx
,
751 unsigned char *output
,
752 const unsigned char *input
)
755 #ifdef rijndael_large_blocks_fixed
756 unsigned int j
, r
, Nb
;
757 unsigned int c2
=0, c3
=0;
759 PRUint8 clone
[RIJNDAEL_MAX_STATE_SIZE
];
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)))) ^
792 rijndael_decryptBlock(AESContext
*cx
,
793 unsigned char *output
,
794 const unsigned char *input
)
797 #ifdef rijndael_large_blocks_fixed
801 PRUint8 clone
[RIJNDAEL_MAX_STATE_SIZE
];
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
--;
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
--;
834 /**************************************************************************
836 * Rijndael modes of operation (ECB and CBC)
838 *************************************************************************/
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
)
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
)
857 inputLen
-= blocksize
;
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
)
870 AESBlockFunc
*encryptor
;
871 unsigned char *lastblock
;
872 unsigned char inblock
[RIJNDAEL_MAX_STATE_SIZE
* 8];
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
];
885 rv
= (*encryptor
)(cx
, output
, inblock
);
886 if (rv
!= SECSuccess
)
888 /* move to the next block */
892 inputLen
-= blocksize
;
894 memcpy(cx
->iv
, lastblock
, blocksize
);
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
)
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
)
915 inputLen
-= blocksize
;
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
)
927 AESBlockFunc
*decryptor
;
928 const unsigned char *in
;
931 unsigned char newIV
[RIJNDAEL_MAX_BLOCKSIZE
];
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
)
946 for (j
=0; j
<blocksize
; ++j
)
947 out
[j
] ^= in
[(int)(j
- blocksize
)];
950 inputLen
-= blocksize
;
953 rv
= (*decryptor
)(cx
, out
, in
);
954 if (rv
!= SECSuccess
)
956 for (j
=0; j
<blocksize
; ++j
)
959 memcpy(cx
->iv
, newIV
, blocksize
);
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
);
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
)
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.
988 keysize
< RIJNDAEL_MIN_BLOCKSIZE
||
989 keysize
> RIJNDAEL_MAX_BLOCKSIZE
||
991 blocksize
< RIJNDAEL_MIN_BLOCKSIZE
||
992 blocksize
> RIJNDAEL_MAX_BLOCKSIZE
||
993 blocksize
% 4 != 0) {
994 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
997 if (mode
!= NSS_AES
&& mode
!= NSS_AES_CBC
) {
998 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1001 if (mode
== NSS_AES_CBC
&& iv
== NULL
) {
1002 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1006 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1009 /* Nb = (block size in bits) / 32 */
1010 cx
->Nb
= blocksize
/ 4;
1011 /* Nk = (key size in bits) / 32 */
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
;
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
);
1027 /* Generate expanded key */
1029 if (rijndael_key_expansion(cx
, key
, Nk
) != SECSuccess
)
1032 if (rijndael_invkey_expansion(cx
, key
, Nk
) != SECSuccess
)
1041 /* AES_CreateContext
1043 * create a new context for Rijndael operations
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();
1052 SECStatus rv
= AES_InitContext(cx
, key
, keysize
, iv
, mode
, encrypt
,
1054 if (rv
!= SECSuccess
) {
1055 AES_DestroyContext(cx
, PR_TRUE
);
1063 * AES_DestroyContext
1065 * Zero an AES cipher context. If freeit is true, also free the pointer
1069 AES_DestroyContext(AESContext
*cx
, PRBool freeit
)
1071 /* memset(cx, 0, sizeof *cx); */
1079 * Encrypt an arbitrary-length buffer. The output buffer must already be
1080 * allocated to at least inputLen.
1083 AES_Encrypt(AESContext
*cx
, unsigned char *output
,
1084 unsigned int *outputLen
, unsigned int maxOutputLen
,
1085 const unsigned char *input
, unsigned int inputLen
)
1089 if (cx
== NULL
|| output
== NULL
|| input
== NULL
) {
1090 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1093 blocksize
= 4 * cx
->Nb
;
1094 if (inputLen
% blocksize
!= 0) {
1095 PORT_SetError(SEC_ERROR_INPUT_LEN
);
1098 if (maxOutputLen
< inputLen
) {
1099 PORT_SetError(SEC_ERROR_OUTPUT_LEN
);
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
)
1112 return (*cx
->worker
)(cx
, output
, outputLen
, maxOutputLen
,
1113 input
, inputLen
, blocksize
);
1119 * Decrypt and arbitrary-length buffer. The output buffer must already be
1120 * allocated to at least inputLen.
1123 AES_Decrypt(AESContext
*cx
, unsigned char *output
,
1124 unsigned int *outputLen
, unsigned int maxOutputLen
,
1125 const unsigned char *input
, unsigned int inputLen
)
1129 if (cx
== NULL
|| output
== NULL
|| input
== NULL
) {
1130 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1133 blocksize
= 4 * cx
->Nb
;
1134 if (inputLen
% blocksize
!= 0) {
1135 PORT_SetError(SEC_ERROR_INPUT_LEN
);
1138 if (maxOutputLen
< inputLen
) {
1139 PORT_SetError(SEC_ERROR_OUTPUT_LEN
);
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
)
1152 return (*cx
->worker
)(cx
, output
, outputLen
, maxOutputLen
,
1153 input
, inputLen
, blocksize
);