Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: mozilla/security/nss/lib/freebl/rijndael.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /* $Id: rijndael.c,v 1.30 2013/01/25 18:02:53 rrelyea%redhat.com Exp $ */
5
6 #ifdef FREEBL_NO_DEPEND
7 #include "stubs.h"
8 #endif
9
10 #include "prinit.h"
11 #include "prerr.h"
12 #include "secerr.h"
13
14 #include "prtypes.h"
15 #include "blapi.h"
16 #include "rijndael.h"
17
18 #include "cts.h"
19 #include "ctr.h"
20 #include "gcm.h"
21
22 #if USE_HW_AES
23 #include "intel-gcm.h"
24 #include "intel-aes.h"
25 #include "mpi.h"
26
27 static int has_intel_aes = 0;
28 static int has_intel_avx = 0;
29 static int has_intel_clmul = 0;
30 static PRBool use_hw_aes = PR_FALSE;
31 static PRBool use_hw_avx = PR_FALSE;
32 static PRBool use_hw_gcm = PR_FALSE;
33 #endif
34
35 /*
36 * There are currently five ways to build this code, varying in performance
37 * and code size.
38 *
39 * RIJNDAEL_INCLUDE_TABLES Include all tables from rijndael32.tab
40 * RIJNDAEL_GENERATE_TABLES Generate tables on first
41 * encryption/decryption, then store them;
42 * use the function gfm
43 * RIJNDAEL_GENERATE_TABLES_MACRO Same as above, but use macros to do
44 * the generation
45 * RIJNDAEL_GENERATE_VALUES Do not store tables, generate the table
46 * values "on-the-fly", using gfm
47 * RIJNDAEL_GENERATE_VALUES_MACRO Same as above, but use macros
48 *
49 * The default is RIJNDAEL_INCLUDE_TABLES.
50 */
51
52 /*
53 * When building RIJNDAEL_INCLUDE_TABLES, includes S**-1, Rcon, T[0..4],
54 * T**-1[0..4], IMXC[0..4]
55 * When building anything else, includes S, S**-1, Rcon
56 */
57 #include "rijndael32.tab"
58
59 #if defined(RIJNDAEL_INCLUDE_TABLES)
60 /*
61 * RIJNDAEL_INCLUDE_TABLES
62 */
63 #define T0(i) _T0[i]
64 #define T1(i) _T1[i]
65 #define T2(i) _T2[i]
66 #define T3(i) _T3[i]
67 #define TInv0(i) _TInv0[i]
68 #define TInv1(i) _TInv1[i]
69 #define TInv2(i) _TInv2[i]
70 #define TInv3(i) _TInv3[i]
71 #define IMXC0(b) _IMXC0[b]
72 #define IMXC1(b) _IMXC1[b]
73 #define IMXC2(b) _IMXC2[b]
74 #define IMXC3(b) _IMXC3[b]
75 /* The S-box can be recovered from the T-tables */
76 #ifdef IS_LITTLE_ENDIAN
77 #define SBOX(b) ((PRUint8)_T3[b])
78 #else
79 #define SBOX(b) ((PRUint8)_T1[b])
80 #endif
81 #define SINV(b) (_SInv[b])
82
83 #else /* not RIJNDAEL_INCLUDE_TABLES */
84
85 /*
86 * Code for generating T-table values.
87 */
88
89 #ifdef IS_LITTLE_ENDIAN
90 #define WORD4(b0, b1, b2, b3) \
91 (((b3) << 24) | ((b2) << 16) | ((b1) << 8) | (b0))
92 #else
93 #define WORD4(b0, b1, b2, b3) \
94 (((b0) << 24) | ((b1) << 16) | ((b2) << 8) | (b3))
95 #endif
96
97 /*
98 * Define the S and S**-1 tables (both have been stored)
99 */
100 #define SBOX(b) (_S[b])
101 #define SINV(b) (_SInv[b])
102
103 /*
104 * The function xtime, used for Galois field multiplication
105 */
106 #define XTIME(a) \
107 ((a & 0x80) ? ((a << 1) ^ 0x1b) : (a << 1))
108
109 /* Choose GFM method (macros or function) */
110 #if defined(RIJNDAEL_GENERATE_TABLES_MACRO) || \
111 defined(RIJNDAEL_GENERATE_VALUES_MACRO)
112
113 /*
114 * Galois field GF(2**8) multipliers, in macro form
115 */
116 #define GFM01(a) \
117 (a) /* a * 01 = a, the identity */
118 #define GFM02(a) \
119 (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
120 #define GFM04(a) \
121 (GFM02(GFM02(a))) /* a * 04 = xtime**2(a) */
122 #define GFM08(a) \
123 (GFM02(GFM04(a))) /* a * 08 = xtime**3(a) */
124 #define GFM03(a) \
125 (GFM01(a) ^ GFM02(a)) /* a * 03 = a * (01 + 02) */
126 #define GFM09(a) \
127 (GFM01(a) ^ GFM08(a)) /* a * 09 = a * (01 + 08) */
128 #define GFM0B(a) \
129 (GFM01(a) ^ GFM02(a) ^ GFM08(a)) /* a * 0B = a * (01 + 02 + 08) */
130 #define GFM0D(a) \
131 (GFM01(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0D = a * (01 + 04 + 08) */
132 #define GFM0E(a) \
133 (GFM02(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0E = a * (02 + 04 + 08) */
134
135 #else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_VALUES */
136
137 /* GF_MULTIPLY
138 *
139 * multiply two bytes represented in GF(2**8), mod (x**4 + 1)
140 */
141 PRUint8 gfm(PRUint8 a, PRUint8 b)
142 {
143 PRUint8 res = 0;
144 while (b > 0) {
145 res = (b & 0x01) ? res ^ a : res;
146 a = XTIME(a);
147 b >>= 1;
148 }
149 return res;
150 }
151
152 #define GFM01(a) \
153 (a) /* a * 01 = a, the identity */
154 #define GFM02(a) \
155 (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
156 #define GFM03(a) \
157 (gfm(a, 0x03)) /* a * 03 */
158 #define GFM09(a) \
159 (gfm(a, 0x09)) /* a * 09 */
160 #define GFM0B(a) \
161 (gfm(a, 0x0B)) /* a * 0B */
162 #define GFM0D(a) \
163 (gfm(a, 0x0D)) /* a * 0D */
164 #define GFM0E(a) \
165 (gfm(a, 0x0E)) /* a * 0E */
166
167 #endif /* choosing GFM function */
168
169 /*
170 * The T-tables
171 */
172 #define G_T0(i) \
173 ( WORD4( GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)) ) )
174 #define G_T1(i) \
175 ( WORD4( GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)) ) )
176 #define G_T2(i) \
177 ( WORD4( GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)) ) )
178 #define G_T3(i) \
179 ( WORD4( GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)) ) )
180
181 /*
182 * The inverse T-tables
183 */
184 #define G_TInv0(i) \
185 ( WORD4( GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)) ) )
186 #define G_TInv1(i) \
187 ( WORD4( GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)) ) )
188 #define G_TInv2(i) \
189 ( WORD4( GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)) ) )
190 #define G_TInv3(i) \
191 ( WORD4( GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)) ) )
192
193 /*
194 * The inverse mix column tables
195 */
196 #define G_IMXC0(i) \
197 ( WORD4( GFM0E(i), GFM09(i), GFM0D(i), GFM0B(i) ) )
198 #define G_IMXC1(i) \
199 ( WORD4( GFM0B(i), GFM0E(i), GFM09(i), GFM0D(i) ) )
200 #define G_IMXC2(i) \
201 ( WORD4( GFM0D(i), GFM0B(i), GFM0E(i), GFM09(i) ) )
202 #define G_IMXC3(i) \
203 ( WORD4( GFM09(i), GFM0D(i), GFM0B(i), GFM0E(i) ) )
204
205 /* Now choose the T-table indexing method */
206 #if defined(RIJNDAEL_GENERATE_VALUES)
207 /* generate values for the tables with a function*/
208 static PRUint32 gen_TInvXi(PRUint8 tx, PRUint8 i)
209 {
210 PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E;
211 si01 = SINV(i);
212 si02 = XTIME(si01);
213 si04 = XTIME(si02);
214 si08 = XTIME(si04);
215 si03 = si02 ^ si01;
216 si09 = si08 ^ si01;
217 si0B = si08 ^ si03;
218 si0D = si09 ^ si04;
219 si0E = si08 ^ si04 ^ si02;
220 switch (tx) {
221 case 0:
222 return WORD4(si0E, si09, si0D, si0B);
223 case 1:
224 return WORD4(si0B, si0E, si09, si0D);
225 case 2:
226 return WORD4(si0D, si0B, si0E, si09);
227 case 3:
228 return WORD4(si09, si0D, si0B, si0E);
229 }
230 return -1;
231 }
232 #define T0(i) G_T0(i)
233 #define T1(i) G_T1(i)
234 #define T2(i) G_T2(i)
235 #define T3(i) G_T3(i)
236 #define TInv0(i) gen_TInvXi(0, i)
237 #define TInv1(i) gen_TInvXi(1, i)
238 #define TInv2(i) gen_TInvXi(2, i)
239 #define TInv3(i) gen_TInvXi(3, i)
240 #define IMXC0(b) G_IMXC0(b)
241 #define IMXC1(b) G_IMXC1(b)
242 #define IMXC2(b) G_IMXC2(b)
243 #define IMXC3(b) G_IMXC3(b)
244 #elif defined(RIJNDAEL_GENERATE_VALUES_MACRO)
245 /* generate values for the tables with macros */
246 #define T0(i) G_T0(i)
247 #define T1(i) G_T1(i)
248 #define T2(i) G_T2(i)
249 #define T3(i) G_T3(i)
250 #define TInv0(i) G_TInv0(i)
251 #define TInv1(i) G_TInv1(i)
252 #define TInv2(i) G_TInv2(i)
253 #define TInv3(i) G_TInv3(i)
254 #define IMXC0(b) G_IMXC0(b)
255 #define IMXC1(b) G_IMXC1(b)
256 #define IMXC2(b) G_IMXC2(b)
257 #define IMXC3(b) G_IMXC3(b)
258 #else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_TABLES_MACRO */
259 /* Generate T and T**-1 table values and store, then index */
260 /* The inverse mix column tables are still generated */
261 #define T0(i) rijndaelTables->T0[i]
262 #define T1(i) rijndaelTables->T1[i]
263 #define T2(i) rijndaelTables->T2[i]
264 #define T3(i) rijndaelTables->T3[i]
265 #define TInv0(i) rijndaelTables->TInv0[i]
266 #define TInv1(i) rijndaelTables->TInv1[i]
267 #define TInv2(i) rijndaelTables->TInv2[i]
268 #define TInv3(i) rijndaelTables->TInv3[i]
269 #define IMXC0(b) G_IMXC0(b)
270 #define IMXC1(b) G_IMXC1(b)
271 #define IMXC2(b) G_IMXC2(b)
272 #define IMXC3(b) G_IMXC3(b)
273 #endif /* choose T-table indexing method */
274
275 #endif /* not RIJNDAEL_INCLUDE_TABLES */
276
277 #if defined(RIJNDAEL_GENERATE_TABLES) || \
278 defined(RIJNDAEL_GENERATE_TABLES_MACRO)
279
280 /* Code to generate and store the tables */
281
282 struct rijndael_tables_str {
283 PRUint32 T0[256];
284 PRUint32 T1[256];
285 PRUint32 T2[256];
286 PRUint32 T3[256];
287 PRUint32 TInv0[256];
288 PRUint32 TInv1[256];
289 PRUint32 TInv2[256];
290 PRUint32 TInv3[256];
291 };
292
293 static struct rijndael_tables_str *rijndaelTables = NULL;
294 static PRCallOnceType coRTInit = { 0, 0, 0 };
295 static PRStatus
296 init_rijndael_tables(void)
297 {
298 PRUint32 i;
299 PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E;
300 struct rijndael_tables_str *rts;
301 rts = (struct rijndael_tables_str *)
302 PORT_Alloc(sizeof(struct rijndael_tables_str));
303 if (!rts) return PR_FAILURE;
304 for (i=0; i<256; i++) {
305 /* The forward values */
306 si01 = SBOX(i);
307 si02 = XTIME(si01);
308 si03 = si02 ^ si01;
309 rts->T0[i] = WORD4(si02, si01, si01, si03);
310 rts->T1[i] = WORD4(si03, si02, si01, si01);
311 rts->T2[i] = WORD4(si01, si03, si02, si01);
312 rts->T3[i] = WORD4(si01, si01, si03, si02);
313 /* The inverse values */
314 si01 = SINV(i);
315 si02 = XTIME(si01);
316 si04 = XTIME(si02);
317 si08 = XTIME(si04);
318 si03 = si02 ^ si01;
319 si09 = si08 ^ si01;
320 si0B = si08 ^ si03;
321 si0D = si09 ^ si04;
322 si0E = si08 ^ si04 ^ si02;
323 rts->TInv0[i] = WORD4(si0E, si09, si0D, si0B);
324 rts->TInv1[i] = WORD4(si0B, si0E, si09, si0D);
325 rts->TInv2[i] = WORD4(si0D, si0B, si0E, si09);
326 rts->TInv3[i] = WORD4(si09, si0D, si0B, si0E);
327 }
328 /* wait until all the values are in to set */
329 rijndaelTables = rts;
330 return PR_SUCCESS;
331 }
332
333 #endif /* code to generate tables */
334
335 /**************************************************************************
336 *
337 * Stuff related to the Rijndael key schedule
338 *
339 *************************************************************************/
340
341 #define SUBBYTE(w) \
342 ((SBOX((w >> 24) & 0xff) << 24) | \
343 (SBOX((w >> 16) & 0xff) << 16) | \
344 (SBOX((w >> 8) & 0xff) << 8) | \
345 (SBOX((w ) & 0xff) ))
346
347 #ifdef IS_LITTLE_ENDIAN
348 #define ROTBYTE(b) \
349 ((b >> 8) | (b << 24))
350 #else
351 #define ROTBYTE(b) \
352 ((b << 8) | (b >> 24))
353 #endif
354
355 /* rijndael_key_expansion7
356 *
357 * Generate the expanded key from the key input by the user.
358 * XXX
359 * Nk == 7 (224 key bits) is a weird case. Since Nk > 6, an added SubByte
360 * transformation is done periodically. The period is every 4 bytes, and
361 * since 7%4 != 0 this happens at different times for each key word (unlike
362 * Nk == 8 where it happens twice in every key word, in the same positions).
363 * For now, I'm implementing this case "dumbly", w/o any unrolling.
364 */
365 static SECStatus
366 rijndael_key_expansion7(AESContext *cx, const unsigned char *key, unsigned int N k)
367 {
368 unsigned int i;
369 PRUint32 *W;
370 PRUint32 *pW;
371 PRUint32 tmp;
372 W = cx->expandedKey;
373 /* 1. the first Nk words contain the cipher key */
374 memcpy(W, key, Nk * 4);
375 i = Nk;
376 /* 2. loop until full expanded key is obtained */
377 pW = W + i - 1;
378 for (; i < cx->Nb * (cx->Nr + 1); ++i) {
379 tmp = *pW++;
380 if (i % Nk == 0)
381 tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
382 else if (i % Nk == 4)
383 tmp = SUBBYTE(tmp);
384 *pW = W[i - Nk] ^ tmp;
385 }
386 return SECSuccess;
387 }
388
389 /* rijndael_key_expansion
390 *
391 * Generate the expanded key from the key input by the user.
392 */
393 static SECStatus
394 rijndael_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk )
395 {
396 unsigned int i;
397 PRUint32 *W;
398 PRUint32 *pW;
399 PRUint32 tmp;
400 unsigned int round_key_words = cx->Nb * (cx->Nr + 1);
401 if (Nk == 7)
402 return rijndael_key_expansion7(cx, key, Nk);
403 W = cx->expandedKey;
404 /* The first Nk words contain the input cipher key */
405 memcpy(W, key, Nk * 4);
406 i = Nk;
407 pW = W + i - 1;
408 /* Loop over all sets of Nk words, except the last */
409 while (i < round_key_words - Nk) {
410 tmp = *pW++;
411 tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
412 *pW = W[i++ - Nk] ^ tmp;
413 tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
414 tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
415 tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
416 if (Nk == 4)
417 continue;
418 switch (Nk) {
419 case 8: tmp = *pW++; tmp = SUBBYTE(tmp); *pW = W[i++ - Nk] ^ tmp;
420 case 7: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
421 case 6: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
422 case 5: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp;
423 }
424 }
425 /* Generate the last word */
426 tmp = *pW++;
427 tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
428 *pW = W[i++ - Nk] ^ tmp;
429 /* There may be overflow here, if Nk % (Nb * (Nr + 1)) > 0. However,
430 * since the above loop generated all but the last Nk key words, there
431 * is no more need for the SubByte transformation.
432 */
433 if (Nk < 8) {
434 for (; i < round_key_words; ++i) {
435 tmp = *pW++;
436 *pW = W[i - Nk] ^ tmp;
437 }
438 } else {
439 /* except in the case when Nk == 8. Then one more SubByte may have
440 * to be performed, at i % Nk == 4.
441 */
442 for (; i < round_key_words; ++i) {
443 tmp = *pW++;
444 if (i % Nk == 4)
445 tmp = SUBBYTE(tmp);
446 *pW = W[i - Nk] ^ tmp;
447 }
448 }
449 return SECSuccess;
450 }
451
452 /* rijndael_invkey_expansion
453 *
454 * Generate the expanded key for the inverse cipher from the key input by
455 * the user.
456 */
457 static SECStatus
458 rijndael_invkey_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
459 {
460 unsigned int r;
461 PRUint32 *roundkeyw;
462 PRUint8 *b;
463 int Nb = cx->Nb;
464 /* begins like usual key expansion ... */
465 if (rijndael_key_expansion(cx, key, Nk) != SECSuccess)
466 return SECFailure;
467 /* ... but has the additional step of InvMixColumn,
468 * excepting the first and last round keys.
469 */
470 roundkeyw = cx->expandedKey + cx->Nb;
471 for (r=1; r<cx->Nr; ++r) {
472 /* each key word, roundkeyw, represents a column in the key
473 * matrix. Each column is multiplied by the InvMixColumn matrix.
474 * [ 0E 0B 0D 09 ] [ b0 ]
475 * [ 09 0E 0B 0D ] * [ b1 ]
476 * [ 0D 09 0E 0B ] [ b2 ]
477 * [ 0B 0D 09 0E ] [ b3 ]
478 */
479 b = (PRUint8 *)roundkeyw;
480 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
481 b = (PRUint8 *)roundkeyw;
482 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
483 b = (PRUint8 *)roundkeyw;
484 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
485 b = (PRUint8 *)roundkeyw;
486 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]);
487 if (Nb <= 4)
488 continue;
489 switch (Nb) {
490 case 8: b = (PRUint8 *)roundkeyw;
491 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
492 IMXC2(b[2]) ^ IMXC3(b[3]);
493 case 7: b = (PRUint8 *)roundkeyw;
494 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
495 IMXC2(b[2]) ^ IMXC3(b[3]);
496 case 6: b = (PRUint8 *)roundkeyw;
497 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
498 IMXC2(b[2]) ^ IMXC3(b[3]);
499 case 5: b = (PRUint8 *)roundkeyw;
500 *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^
501 IMXC2(b[2]) ^ IMXC3(b[3]);
502 }
503 }
504 return SECSuccess;
505 }
506 /**************************************************************************
507 *
508 * Stuff related to Rijndael encryption/decryption, optimized for
509 * a 128-bit blocksize.
510 *
511 *************************************************************************/
512
513 #ifdef IS_LITTLE_ENDIAN
514 #define BYTE0WORD(w) ((w) & 0x000000ff)
515 #define BYTE1WORD(w) ((w) & 0x0000ff00)
516 #define BYTE2WORD(w) ((w) & 0x00ff0000)
517 #define BYTE3WORD(w) ((w) & 0xff000000)
518 #else
519 #define BYTE0WORD(w) ((w) & 0xff000000)
520 #define BYTE1WORD(w) ((w) & 0x00ff0000)
521 #define BYTE2WORD(w) ((w) & 0x0000ff00)
522 #define BYTE3WORD(w) ((w) & 0x000000ff)
523 #endif
524
525 typedef union {
526 PRUint32 w[4];
527 PRUint8 b[16];
528 } rijndael_state;
529
530 #define COLUMN_0(state) state.w[0]
531 #define COLUMN_1(state) state.w[1]
532 #define COLUMN_2(state) state.w[2]
533 #define COLUMN_3(state) state.w[3]
534
535 #define STATE_BYTE(i) state.b[i]
536
537 static SECStatus
538 rijndael_encryptBlock128(AESContext *cx,
539 unsigned char *output,
540 const unsigned char *input)
541 {
542 unsigned int r;
543 PRUint32 *roundkeyw;
544 rijndael_state state;
545 PRUint32 C0, C1, C2, C3;
546 #if defined(NSS_X86_OR_X64)
547 #define pIn input
548 #define pOut output
549 #else
550 unsigned char *pIn, *pOut;
551 PRUint32 inBuf[4], outBuf[4];
552
553 if ((ptrdiff_t)input & 0x3) {
554 memcpy(inBuf, input, sizeof inBuf);
555 pIn = (unsigned char *)inBuf;
556 } else {
557 pIn = (unsigned char *)input;
558 }
559 if ((ptrdiff_t)output & 0x3) {
560 pOut = (unsigned char *)outBuf;
561 } else {
562 pOut = (unsigned char *)output;
563 }
564 #endif
565 roundkeyw = cx->expandedKey;
566 /* Step 1: Add Round Key 0 to initial state */
567 COLUMN_0(state) = *((PRUint32 *)(pIn )) ^ *roundkeyw++;
568 COLUMN_1(state) = *((PRUint32 *)(pIn + 4 )) ^ *roundkeyw++;
569 COLUMN_2(state) = *((PRUint32 *)(pIn + 8 )) ^ *roundkeyw++;
570 COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw++;
571 /* Step 2: Loop over rounds [1..NR-1] */
572 for (r=1; r<cx->Nr; ++r) {
573 /* Do ShiftRow, ByteSub, and MixColumn all at once */
574 C0 = T0(STATE_BYTE(0)) ^
575 T1(STATE_BYTE(5)) ^
576 T2(STATE_BYTE(10)) ^
577 T3(STATE_BYTE(15));
578 C1 = T0(STATE_BYTE(4)) ^
579 T1(STATE_BYTE(9)) ^
580 T2(STATE_BYTE(14)) ^
581 T3(STATE_BYTE(3));
582 C2 = T0(STATE_BYTE(8)) ^
583 T1(STATE_BYTE(13)) ^
584 T2(STATE_BYTE(2)) ^
585 T3(STATE_BYTE(7));
586 C3 = T0(STATE_BYTE(12)) ^
587 T1(STATE_BYTE(1)) ^
588 T2(STATE_BYTE(6)) ^
589 T3(STATE_BYTE(11));
590 /* Round key addition */
591 COLUMN_0(state) = C0 ^ *roundkeyw++;
592 COLUMN_1(state) = C1 ^ *roundkeyw++;
593 COLUMN_2(state) = C2 ^ *roundkeyw++;
594 COLUMN_3(state) = C3 ^ *roundkeyw++;
595 }
596 /* Step 3: Do the last round */
597 /* Final round does not employ MixColumn */
598 C0 = ((BYTE0WORD(T2(STATE_BYTE(0)))) |
599 (BYTE1WORD(T3(STATE_BYTE(5)))) |
600 (BYTE2WORD(T0(STATE_BYTE(10)))) |
601 (BYTE3WORD(T1(STATE_BYTE(15))))) ^
602 *roundkeyw++;
603 C1 = ((BYTE0WORD(T2(STATE_BYTE(4)))) |
604 (BYTE1WORD(T3(STATE_BYTE(9)))) |
605 (BYTE2WORD(T0(STATE_BYTE(14)))) |
606 (BYTE3WORD(T1(STATE_BYTE(3))))) ^
607 *roundkeyw++;
608 C2 = ((BYTE0WORD(T2(STATE_BYTE(8)))) |
609 (BYTE1WORD(T3(STATE_BYTE(13)))) |
610 (BYTE2WORD(T0(STATE_BYTE(2)))) |
611 (BYTE3WORD(T1(STATE_BYTE(7))))) ^
612 *roundkeyw++;
613 C3 = ((BYTE0WORD(T2(STATE_BYTE(12)))) |
614 (BYTE1WORD(T3(STATE_BYTE(1)))) |
615 (BYTE2WORD(T0(STATE_BYTE(6)))) |
616 (BYTE3WORD(T1(STATE_BYTE(11))))) ^
617 *roundkeyw++;
618 *((PRUint32 *) pOut ) = C0;
619 *((PRUint32 *)(pOut + 4)) = C1;
620 *((PRUint32 *)(pOut + 8)) = C2;
621 *((PRUint32 *)(pOut + 12)) = C3;
622 #if defined(NSS_X86_OR_X64)
623 #undef pIn
624 #undef pOut
625 #else
626 if ((ptrdiff_t)output & 0x3) {
627 memcpy(output, outBuf, sizeof outBuf);
628 }
629 #endif
630 return SECSuccess;
631 }
632
633 static SECStatus
634 rijndael_decryptBlock128(AESContext *cx,
635 unsigned char *output,
636 const unsigned char *input)
637 {
638 int r;
639 PRUint32 *roundkeyw;
640 rijndael_state state;
641 PRUint32 C0, C1, C2, C3;
642 #if defined(NSS_X86_OR_X64)
643 #define pIn input
644 #define pOut output
645 #else
646 unsigned char *pIn, *pOut;
647 PRUint32 inBuf[4], outBuf[4];
648
649 if ((ptrdiff_t)input & 0x3) {
650 memcpy(inBuf, input, sizeof inBuf);
651 pIn = (unsigned char *)inBuf;
652 } else {
653 pIn = (unsigned char *)input;
654 }
655 if ((ptrdiff_t)output & 0x3) {
656 pOut = (unsigned char *)outBuf;
657 } else {
658 pOut = (unsigned char *)output;
659 }
660 #endif
661 roundkeyw = cx->expandedKey + cx->Nb * cx->Nr + 3;
662 /* reverse the final key addition */
663 COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw--;
664 COLUMN_2(state) = *((PRUint32 *)(pIn + 8)) ^ *roundkeyw--;
665 COLUMN_1(state) = *((PRUint32 *)(pIn + 4)) ^ *roundkeyw--;
666 COLUMN_0(state) = *((PRUint32 *)(pIn )) ^ *roundkeyw--;
667 /* Loop over rounds in reverse [NR..1] */
668 for (r=cx->Nr; r>1; --r) {
669 /* Invert the (InvByteSub*InvMixColumn)(InvShiftRow(state)) */
670 C0 = TInv0(STATE_BYTE(0)) ^
671 TInv1(STATE_BYTE(13)) ^
672 TInv2(STATE_BYTE(10)) ^
673 TInv3(STATE_BYTE(7));
674 C1 = TInv0(STATE_BYTE(4)) ^
675 TInv1(STATE_BYTE(1)) ^
676 TInv2(STATE_BYTE(14)) ^
677 TInv3(STATE_BYTE(11));
678 C2 = TInv0(STATE_BYTE(8)) ^
679 TInv1(STATE_BYTE(5)) ^
680 TInv2(STATE_BYTE(2)) ^
681 TInv3(STATE_BYTE(15));
682 C3 = TInv0(STATE_BYTE(12)) ^
683 TInv1(STATE_BYTE(9)) ^
684 TInv2(STATE_BYTE(6)) ^
685 TInv3(STATE_BYTE(3));
686 /* Invert the key addition step */
687 COLUMN_3(state) = C3 ^ *roundkeyw--;
688 COLUMN_2(state) = C2 ^ *roundkeyw--;
689 COLUMN_1(state) = C1 ^ *roundkeyw--;
690 COLUMN_0(state) = C0 ^ *roundkeyw--;
691 }
692 /* inverse sub */
693 pOut[ 0] = SINV(STATE_BYTE( 0));
694 pOut[ 1] = SINV(STATE_BYTE(13));
695 pOut[ 2] = SINV(STATE_BYTE(10));
696 pOut[ 3] = SINV(STATE_BYTE( 7));
697 pOut[ 4] = SINV(STATE_BYTE( 4));
698 pOut[ 5] = SINV(STATE_BYTE( 1));
699 pOut[ 6] = SINV(STATE_BYTE(14));
700 pOut[ 7] = SINV(STATE_BYTE(11));
701 pOut[ 8] = SINV(STATE_BYTE( 8));
702 pOut[ 9] = SINV(STATE_BYTE( 5));
703 pOut[10] = SINV(STATE_BYTE( 2));
704 pOut[11] = SINV(STATE_BYTE(15));
705 pOut[12] = SINV(STATE_BYTE(12));
706 pOut[13] = SINV(STATE_BYTE( 9));
707 pOut[14] = SINV(STATE_BYTE( 6));
708 pOut[15] = SINV(STATE_BYTE( 3));
709 /* final key addition */
710 *((PRUint32 *)(pOut + 12)) ^= *roundkeyw--;
711 *((PRUint32 *)(pOut + 8)) ^= *roundkeyw--;
712 *((PRUint32 *)(pOut + 4)) ^= *roundkeyw--;
713 *((PRUint32 *) pOut ) ^= *roundkeyw--;
714 #if defined(NSS_X86_OR_X64)
715 #undef pIn
716 #undef pOut
717 #else
718 if ((ptrdiff_t)output & 0x3) {
719 memcpy(output, outBuf, sizeof outBuf);
720 }
721 #endif
722 return SECSuccess;
723 }
724
725 /**************************************************************************
726 *
727 * Stuff related to general Rijndael encryption/decryption, for blocksizes
728 * greater than 128 bits.
729 *
730 * XXX This code is currently untested! So far, AES specs have only been
731 * released for 128 bit blocksizes. This will be tested, but for now
732 * only the code above has been tested using known values.
733 *
734 *************************************************************************/
735
736 #define COLUMN(array, j) *((PRUint32 *)(array + j))
737
738 SECStatus
739 rijndael_encryptBlock(AESContext *cx,
740 unsigned char *output,
741 const unsigned char *input)
742 {
743 return SECFailure;
744 #ifdef rijndael_large_blocks_fixed
745 unsigned int j, r, Nb;
746 unsigned int c2=0, c3=0;
747 PRUint32 *roundkeyw;
748 PRUint8 clone[RIJNDAEL_MAX_STATE_SIZE];
749 Nb = cx->Nb;
750 roundkeyw = cx->expandedKey;
751 /* Step 1: Add Round Key 0 to initial state */
752 for (j=0; j<4*Nb; j+=4) {
753 COLUMN(clone, j) = COLUMN(input, j) ^ *roundkeyw++;
754 }
755 /* Step 2: Loop over rounds [1..NR-1] */
756 for (r=1; r<cx->Nr; ++r) {
757 for (j=0; j<Nb; ++j) {
758 COLUMN(output, j) = T0(STATE_BYTE(4* j )) ^
759 T1(STATE_BYTE(4*((j+ 1)%Nb)+1)) ^
760 T2(STATE_BYTE(4*((j+c2)%Nb)+2)) ^
761 T3(STATE_BYTE(4*((j+c3)%Nb)+3));
762 }
763 for (j=0; j<4*Nb; j+=4) {
764 COLUMN(clone, j) = COLUMN(output, j) ^ *roundkeyw++;
765 }
766 }
767 /* Step 3: Do the last round */
768 /* Final round does not employ MixColumn */
769 for (j=0; j<Nb; ++j) {
770 COLUMN(output, j) = ((BYTE0WORD(T2(STATE_BYTE(4* j )))) |
771 (BYTE1WORD(T3(STATE_BYTE(4*(j+ 1)%Nb)+1))) |
772 (BYTE2WORD(T0(STATE_BYTE(4*(j+c2)%Nb)+2))) |
773 (BYTE3WORD(T1(STATE_BYTE(4*(j+c3)%Nb)+3)))) ^
774 *roundkeyw++;
775 }
776 return SECSuccess;
777 #endif
778 }
779
780 SECStatus
781 rijndael_decryptBlock(AESContext *cx,
782 unsigned char *output,
783 const unsigned char *input)
784 {
785 return SECFailure;
786 #ifdef rijndael_large_blocks_fixed
787 int j, r, Nb;
788 int c2=0, c3=0;
789 PRUint32 *roundkeyw;
790 PRUint8 clone[RIJNDAEL_MAX_STATE_SIZE];
791 Nb = cx->Nb;
792 roundkeyw = cx->expandedKey + cx->Nb * cx->Nr + 3;
793 /* reverse key addition */
794 for (j=4*Nb; j>=0; j-=4) {
795 COLUMN(clone, j) = COLUMN(input, j) ^ *roundkeyw--;
796 }
797 /* Loop over rounds in reverse [NR..1] */
798 for (r=cx->Nr; r>1; --r) {
799 /* Invert the (InvByteSub*InvMixColumn)(InvShiftRow(state)) */
800 for (j=0; j<Nb; ++j) {
801 COLUMN(output, 4*j) = TInv0(STATE_BYTE(4* j )) ^
802 TInv1(STATE_BYTE(4*(j+Nb- 1)%Nb)+1) ^
803 TInv2(STATE_BYTE(4*(j+Nb-c2)%Nb)+2) ^
804 TInv3(STATE_BYTE(4*(j+Nb-c3)%Nb)+3);
805 }
806 /* Invert the key addition step */
807 for (j=4*Nb; j>=0; j-=4) {
808 COLUMN(clone, j) = COLUMN(output, j) ^ *roundkeyw--;
809 }
810 }
811 /* inverse sub */
812 for (j=0; j<4*Nb; ++j) {
813 output[j] = SINV(clone[j]);
814 }
815 /* final key addition */
816 for (j=4*Nb; j>=0; j-=4) {
817 COLUMN(output, j) ^= *roundkeyw--;
818 }
819 return SECSuccess;
820 #endif
821 }
822
823 /**************************************************************************
824 *
825 * Rijndael modes of operation (ECB and CBC)
826 *
827 *************************************************************************/
828
829 static SECStatus
830 rijndael_encryptECB(AESContext *cx, unsigned char *output,
831 unsigned int *outputLen, unsigned int maxOutputLen,
832 const unsigned char *input, unsigned int inputLen,
833 unsigned int blocksize)
834 {
835 SECStatus rv;
836 AESBlockFunc *encryptor;
837
838
839 encryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE)
840 ? &rijndael_encryptBlock128
841 : &rijndael_encryptBlock;
842 while (inputLen > 0) {
843 rv = (*encryptor)(cx, output, input);
844 if (rv != SECSuccess)
845 return rv;
846 output += blocksize;
847 input += blocksize;
848 inputLen -= blocksize;
849 }
850 return SECSuccess;
851 }
852
853 static SECStatus
854 rijndael_encryptCBC(AESContext *cx, unsigned char *output,
855 unsigned int *outputLen, unsigned int maxOutputLen,
856 const unsigned char *input, unsigned int inputLen,
857 unsigned int blocksize)
858 {
859 unsigned int j;
860 SECStatus rv;
861 AESBlockFunc *encryptor;
862 unsigned char *lastblock;
863 unsigned char inblock[RIJNDAEL_MAX_STATE_SIZE * 8];
864
865 if (!inputLen)
866 return SECSuccess;
867 lastblock = cx->iv;
868 encryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE)
869 ? &rijndael_encryptBlock128
870 : &rijndael_encryptBlock;
871 while (inputLen > 0) {
872 /* XOR with the last block (IV if first block) */
873 for (j=0; j<blocksize; ++j)
874 inblock[j] = input[j] ^ lastblock[j];
875 /* encrypt */
876 rv = (*encryptor)(cx, output, inblock);
877 if (rv != SECSuccess)
878 return rv;
879 /* move to the next block */
880 lastblock = output;
881 output += blocksize;
882 input += blocksize;
883 inputLen -= blocksize;
884 }
885 memcpy(cx->iv, lastblock, blocksize);
886 return SECSuccess;
887 }
888
889 static SECStatus
890 rijndael_decryptECB(AESContext *cx, unsigned char *output,
891 unsigned int *outputLen, unsigned int maxOutputLen,
892 const unsigned char *input, unsigned int inputLen,
893 unsigned int blocksize)
894 {
895 SECStatus rv;
896 AESBlockFunc *decryptor;
897
898 decryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE)
899 ? &rijndael_decryptBlock128
900 : &rijndael_decryptBlock;
901 while (inputLen > 0) {
902 rv = (*decryptor)(cx, output, input);
903 if (rv != SECSuccess)
904 return rv;
905 output += blocksize;
906 input += blocksize;
907 inputLen -= blocksize;
908 }
909 return SECSuccess;
910 }
911
912 static SECStatus
913 rijndael_decryptCBC(AESContext *cx, unsigned char *output,
914 unsigned int *outputLen, unsigned int maxOutputLen,
915 const unsigned char *input, unsigned int inputLen,
916 unsigned int blocksize)
917 {
918 SECStatus rv;
919 AESBlockFunc *decryptor;
920 const unsigned char *in;
921 unsigned char *out;
922 unsigned int j;
923 unsigned char newIV[RIJNDAEL_MAX_BLOCKSIZE];
924
925
926 if (!inputLen)
927 return SECSuccess;
928 PORT_Assert(output - input >= 0 || input - output >= (int)inputLen );
929 decryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE)
930 ? &rijndael_decryptBlock128
931 : &rijndael_decryptBlock;
932 in = input + (inputLen - blocksize);
933 memcpy(newIV, in, blocksize);
934 out = output + (inputLen - blocksize);
935 while (inputLen > blocksize) {
936 rv = (*decryptor)(cx, out, in);
937 if (rv != SECSuccess)
938 return rv;
939 for (j=0; j<blocksize; ++j)
940 out[j] ^= in[(int)(j - blocksize)];
941 out -= blocksize;
942 in -= blocksize;
943 inputLen -= blocksize;
944 }
945 if (in == input) {
946 rv = (*decryptor)(cx, out, in);
947 if (rv != SECSuccess)
948 return rv;
949 for (j=0; j<blocksize; ++j)
950 out[j] ^= cx->iv[j];
951 }
952 memcpy(cx->iv, newIV, blocksize);
953 return SECSuccess;
954 }
955
956 /************************************************************************
957 *
958 * BLAPI Interface functions
959 *
960 * The following functions implement the encryption routines defined in
961 * BLAPI for the AES cipher, Rijndael.
962 *
963 ***********************************************************************/
964
965 AESContext * AES_AllocateContext(void)
966 {
967 return PORT_ZNew(AESContext);
968 }
969
970
971 /*
972 ** Initialize a new AES context suitable for AES encryption/decryption in
973 ** the ECB or CBC mode.
974 ** "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC
975 */
976 static SECStatus
977 aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
978 const unsigned char *iv, int mode, unsigned int encrypt,
979 unsigned int blocksize)
980 {
981 unsigned int Nk;
982 /* According to Rijndael AES Proposal, section 12.1, block and key
983 * lengths between 128 and 256 bits are supported, as long as the
984 * length in bytes is divisible by 4.
985 */
986 if (key == NULL ||
987 keysize < RIJNDAEL_MIN_BLOCKSIZE ||
988 keysize > RIJNDAEL_MAX_BLOCKSIZE ||
989 keysize % 4 != 0 ||
990 blocksize < RIJNDAEL_MIN_BLOCKSIZE ||
991 blocksize > RIJNDAEL_MAX_BLOCKSIZE ||
992 blocksize % 4 != 0) {
993 PORT_SetError(SEC_ERROR_INVALID_ARGS);
994 return SECFailure;
995 }
996 if (mode != NSS_AES && mode != NSS_AES_CBC) {
997 PORT_SetError(SEC_ERROR_INVALID_ARGS);
998 return SECFailure;
999 }
1000 if (mode == NSS_AES_CBC && iv == NULL) {
1001 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1002 return SECFailure;
1003 }
1004 if (!cx) {
1005 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1006 return SECFailure;
1007 }
1008 #if USE_HW_AES
1009 if (has_intel_aes == 0) {
1010 unsigned long eax, ebx, ecx, edx;
1011 char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES");
1012
1013 if (disable_hw_aes == NULL) {
1014 freebl_cpuid(1, &eax, &ebx, &ecx, &edx);
1015 has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1;
1016 has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1;
1017 has_intel_avx = (ecx & (1 << 28)) != 0 ? 1 : -1;
1018 } else {
1019 has_intel_aes = -1;
1020 has_intel_avx = -1;
1021 has_intel_clmul = -1;
1022 }
1023 }
1024 use_hw_aes = (PRBool)
1025 (has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16);
1026 use_hw_gcm = (PRBool)
1027 (use_hw_aes && has_intel_avx>0 && has_intel_clmul>0);
1028 #endif
1029 /* Nb = (block size in bits) / 32 */
1030 cx->Nb = blocksize / 4;
1031 /* Nk = (key size in bits) / 32 */
1032 Nk = keysize / 4;
1033 /* Obtain number of rounds from "table" */
1034 cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb);
1035 /* copy in the iv, if neccessary */
1036 if (mode == NSS_AES_CBC) {
1037 memcpy(cx->iv, iv, blocksize);
1038 #if USE_HW_AES
1039 if (use_hw_aes) {
1040 cx->worker = (freeblCipherFunc)
1041 intel_aes_cbc_worker(encrypt, keysize);
1042 } else
1043 #endif
1044 cx->worker = (freeblCipherFunc) (encrypt
1045 ? &rijndael_encryptCBC : &rijndael_decryptCBC);
1046 } else {
1047 #if USE_HW_AES
1048 if (use_hw_aes) {
1049 cx->worker = (freeblCipherFunc)
1050 intel_aes_ecb_worker(encrypt, keysize);
1051 } else
1052 #endif
1053 cx->worker = (freeblCipherFunc) (encrypt
1054 ? &rijndael_encryptECB : &rijndael_decryptECB);
1055 }
1056 PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE);
1057 if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) {
1058 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1059 goto cleanup;
1060 }
1061 #ifdef USE_HW_AES
1062 if (use_hw_aes) {
1063 intel_aes_init(encrypt, keysize);
1064 } else
1065 #endif
1066 {
1067
1068 #if defined(RIJNDAEL_GENERATE_TABLES) || \
1069 defined(RIJNDAEL_GENERATE_TABLES_MACRO)
1070 if (rijndaelTables == NULL) {
1071 if (PR_CallOnce(&coRTInit, init_rijndael_tables)
1072 != PR_SUCCESS) {
1073 return SecFailure;
1074 }
1075 }
1076 #endif
1077 /* Generate expanded key */
1078 if (encrypt) {
1079 if (rijndael_key_expansion(cx, key, Nk) != SECSuccess)
1080 goto cleanup;
1081 } else {
1082 if (rijndael_invkey_expansion(cx, key, Nk) != SECSuccess)
1083 goto cleanup;
1084 }
1085 }
1086 cx->worker_cx = cx;
1087 cx->destroy = NULL;
1088 cx->isBlock = PR_TRUE;
1089 return SECSuccess;
1090 cleanup:
1091 return SECFailure;
1092 }
1093
1094 SECStatus
1095 AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
1096 const unsigned char *iv, int mode, unsigned int encrypt,
1097 unsigned int blocksize)
1098 {
1099 int basemode = mode;
1100 PRBool baseencrypt = encrypt;
1101 SECStatus rv;
1102
1103 switch (mode) {
1104 case NSS_AES_CTS:
1105 basemode = NSS_AES_CBC;
1106 break;
1107 case NSS_AES_GCM:
1108 case NSS_AES_CTR:
1109 basemode = NSS_AES;
1110 baseencrypt = PR_TRUE;
1111 break;
1112 }
1113 /* make sure enough is initializes so we can safely call Destroy */
1114 cx->worker_cx = NULL;
1115 cx->destroy = NULL;
1116 rv = aes_InitContext(cx, key, keysize, iv, basemode,
1117 baseencrypt, blocksize);
1118 if (rv != SECSuccess) {
1119 AES_DestroyContext(cx, PR_FALSE);
1120 return rv;
1121 }
1122
1123 /* finally, set up any mode specific contexts */
1124 switch (mode) {
1125 case NSS_AES_CTS:
1126 cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize);
1127 cx->worker = (freeblCipherFunc)
1128 (encrypt ? CTS_EncryptUpdate : CTS_DecryptUpdate);
1129 cx->destroy = (freeblDestroyFunc) CTS_DestroyContext;
1130 cx->isBlock = PR_FALSE;
1131 break;
1132 case NSS_AES_GCM:
1133 #if USE_HW_AES
1134 if(use_hw_gcm) {
1135 cx->worker_cx = intel_AES_GCM_CreateContext(cx, cx->worker, iv, blocksize);
1136 cx->worker = (freeblCipherFunc)
1137 (encrypt ? intel_AES_GCM_EncryptUpdate : intel_AES_GCM_D ecryptUpdate);
1138 cx->destroy = (freeblDestroyFunc) intel_AES_GCM_DestroyContext;
1139 cx->isBlock = PR_FALSE;
1140 } else
1141 #endif
1142 {
1143 cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize);
1144 cx->worker = (freeblCipherFunc)
1145 (encrypt ? GCM_EncryptUpdate : GCM_DecryptUpdate);
1146 cx->destroy = (freeblDestroyFunc) GCM_DestroyContext;
1147 cx->isBlock = PR_FALSE;
1148 }
1149 break;
1150 case NSS_AES_CTR:
1151 cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv, blocksize);
1152 cx->worker = (freeblCipherFunc) CTR_Update ;
1153 cx->destroy = (freeblDestroyFunc) CTR_DestroyContext;
1154 cx->isBlock = PR_FALSE;
1155 break;
1156 default:
1157 /* everything has already been set up by aes_InitContext, just
1158 * return */
1159 return SECSuccess;
1160 }
1161 /* check to see if we succeeded in getting the worker context */
1162 if (cx->worker_cx == NULL) {
1163 /* no, just destroy the existing context */
1164 cx->destroy = NULL; /* paranoia, though you can see a dozen lines */
1165 /* below that this isn't necessary */
1166 AES_DestroyContext(cx, PR_FALSE);
1167 return SECFailure;
1168 }
1169 return SECSuccess;
1170 }
1171
1172 /* AES_CreateContext
1173 *
1174 * create a new context for Rijndael operations
1175 */
1176 AESContext *
1177 AES_CreateContext(const unsigned char *key, const unsigned char *iv,
1178 int mode, int encrypt,
1179 unsigned int keysize, unsigned int blocksize)
1180 {
1181 AESContext *cx = AES_AllocateContext();
1182 if (cx) {
1183 SECStatus rv = AES_InitContext(cx, key, keysize, iv, mode, encrypt,
1184 blocksize);
1185 if (rv != SECSuccess) {
1186 AES_DestroyContext(cx, PR_TRUE);
1187 cx = NULL;
1188 }
1189 }
1190 return cx;
1191 }
1192
1193 /*
1194 * AES_DestroyContext
1195 *
1196 * Zero an AES cipher context. If freeit is true, also free the pointer
1197 * to the context.
1198 */
1199 void
1200 AES_DestroyContext(AESContext *cx, PRBool freeit)
1201 {
1202 if (cx->worker_cx && cx->destroy) {
1203 (*cx->destroy)(cx->worker_cx, PR_TRUE);
1204 cx->worker_cx = NULL;
1205 cx->destroy = NULL;
1206 }
1207 if (freeit)
1208 PORT_Free(cx);
1209 }
1210
1211 /*
1212 * AES_Encrypt
1213 *
1214 * Encrypt an arbitrary-length buffer. The output buffer must already be
1215 * allocated to at least inputLen.
1216 */
1217 SECStatus
1218 AES_Encrypt(AESContext *cx, unsigned char *output,
1219 unsigned int *outputLen, unsigned int maxOutputLen,
1220 const unsigned char *input, unsigned int inputLen)
1221 {
1222 int blocksize;
1223 /* Check args */
1224 if (cx == NULL || output == NULL || (input == NULL && inputLen != 0)) {
1225 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1226 return SECFailure;
1227 }
1228 blocksize = 4 * cx->Nb;
1229 if (cx->isBlock && (inputLen % blocksize != 0)) {
1230 PORT_SetError(SEC_ERROR_INPUT_LEN);
1231 return SECFailure;
1232 }
1233 if (maxOutputLen < inputLen) {
1234 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1235 return SECFailure;
1236 }
1237 *outputLen = inputLen;
1238 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
1239 input, inputLen, blocksize);
1240 }
1241
1242 /*
1243 * AES_Decrypt
1244 *
1245 * Decrypt and arbitrary-length buffer. The output buffer must already be
1246 * allocated to at least inputLen.
1247 */
1248 SECStatus
1249 AES_Decrypt(AESContext *cx, unsigned char *output,
1250 unsigned int *outputLen, unsigned int maxOutputLen,
1251 const unsigned char *input, unsigned int inputLen)
1252 {
1253 int blocksize;
1254 /* Check args */
1255 if (cx == NULL || output == NULL || (input == NULL && inputLen != 0)) {
1256 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1257 return SECFailure;
1258 }
1259 blocksize = 4 * cx->Nb;
1260 if (cx->isBlock && (inputLen % blocksize != 0)) {
1261 PORT_SetError(SEC_ERROR_INPUT_LEN);
1262 return SECFailure;
1263 }
1264 if (maxOutputLen < inputLen) {
1265 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1266 return SECFailure;
1267 }
1268 *outputLen = inputLen;
1269 return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
1270 input, inputLen, blocksize);
1271 }
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/freebl/rijndael.h ('k') | mozilla/security/nss/lib/freebl/rijndael32.tab » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698