| Index: mozilla/security/nss/lib/freebl/rijndael.c | 
| =================================================================== | 
| --- mozilla/security/nss/lib/freebl/rijndael.c	(revision 191424) | 
| +++ mozilla/security/nss/lib/freebl/rijndael.c	(working copy) | 
| @@ -1,1271 +0,0 @@ | 
| -/* This Source Code Form is subject to the terms of the Mozilla Public | 
| - * License, v. 2.0. If a copy of the MPL was not distributed with this | 
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 
| -/* $Id: rijndael.c,v 1.30 2013/01/25 18:02:53 rrelyea%redhat.com Exp $ */ | 
| - | 
| -#ifdef FREEBL_NO_DEPEND | 
| -#include "stubs.h" | 
| -#endif | 
| - | 
| -#include "prinit.h" | 
| -#include "prerr.h" | 
| -#include "secerr.h" | 
| - | 
| -#include "prtypes.h" | 
| -#include "blapi.h" | 
| -#include "rijndael.h" | 
| - | 
| -#include "cts.h" | 
| -#include "ctr.h" | 
| -#include "gcm.h" | 
| - | 
| -#if USE_HW_AES | 
| -#include "intel-gcm.h" | 
| -#include "intel-aes.h" | 
| -#include "mpi.h" | 
| - | 
| -static int has_intel_aes = 0; | 
| -static int has_intel_avx = 0; | 
| -static int has_intel_clmul = 0; | 
| -static PRBool use_hw_aes = PR_FALSE; | 
| -static PRBool use_hw_avx = PR_FALSE; | 
| -static PRBool use_hw_gcm = PR_FALSE; | 
| -#endif | 
| - | 
| -/* | 
| - * There are currently five ways to build this code, varying in performance | 
| - * and code size. | 
| - * | 
| - * RIJNDAEL_INCLUDE_TABLES         Include all tables from rijndael32.tab | 
| - * RIJNDAEL_GENERATE_TABLES        Generate tables on first | 
| - *                                 encryption/decryption, then store them; | 
| - *                                 use the function gfm | 
| - * RIJNDAEL_GENERATE_TABLES_MACRO  Same as above, but use macros to do | 
| - *                                 the generation | 
| - * RIJNDAEL_GENERATE_VALUES        Do not store tables, generate the table | 
| - *                                 values "on-the-fly", using gfm | 
| - * RIJNDAEL_GENERATE_VALUES_MACRO  Same as above, but use macros | 
| - * | 
| - * The default is RIJNDAEL_INCLUDE_TABLES. | 
| - */ | 
| - | 
| -/* | 
| - * When building RIJNDAEL_INCLUDE_TABLES, includes S**-1, Rcon, T[0..4], | 
| - *                                                 T**-1[0..4], IMXC[0..4] | 
| - * When building anything else, includes S, S**-1, Rcon | 
| - */ | 
| -#include "rijndael32.tab" | 
| - | 
| -#if defined(RIJNDAEL_INCLUDE_TABLES) | 
| -/* | 
| - * RIJNDAEL_INCLUDE_TABLES | 
| - */ | 
| -#define T0(i)    _T0[i] | 
| -#define T1(i)    _T1[i] | 
| -#define T2(i)    _T2[i] | 
| -#define T3(i)    _T3[i] | 
| -#define TInv0(i) _TInv0[i] | 
| -#define TInv1(i) _TInv1[i] | 
| -#define TInv2(i) _TInv2[i] | 
| -#define TInv3(i) _TInv3[i] | 
| -#define IMXC0(b) _IMXC0[b] | 
| -#define IMXC1(b) _IMXC1[b] | 
| -#define IMXC2(b) _IMXC2[b] | 
| -#define IMXC3(b) _IMXC3[b] | 
| -/* The S-box can be recovered from the T-tables */ | 
| -#ifdef IS_LITTLE_ENDIAN | 
| -#define SBOX(b)    ((PRUint8)_T3[b]) | 
| -#else | 
| -#define SBOX(b)    ((PRUint8)_T1[b]) | 
| -#endif | 
| -#define SINV(b) (_SInv[b]) | 
| - | 
| -#else /* not RIJNDAEL_INCLUDE_TABLES */ | 
| - | 
| -/* | 
| - * Code for generating T-table values. | 
| - */ | 
| - | 
| -#ifdef IS_LITTLE_ENDIAN | 
| -#define WORD4(b0, b1, b2, b3) \ | 
| -    (((b3) << 24) | ((b2) << 16) | ((b1) << 8) | (b0)) | 
| -#else | 
| -#define WORD4(b0, b1, b2, b3) \ | 
| -    (((b0) << 24) | ((b1) << 16) | ((b2) << 8) | (b3)) | 
| -#endif | 
| - | 
| -/* | 
| - * Define the S and S**-1 tables (both have been stored) | 
| - */ | 
| -#define SBOX(b)    (_S[b]) | 
| -#define SINV(b) (_SInv[b]) | 
| - | 
| -/* | 
| - * The function xtime, used for Galois field multiplication | 
| - */ | 
| -#define XTIME(a) \ | 
| -    ((a & 0x80) ? ((a << 1) ^ 0x1b) : (a << 1)) | 
| - | 
| -/* Choose GFM method (macros or function) */ | 
| -#if defined(RIJNDAEL_GENERATE_TABLES_MACRO) ||  \ | 
| -    defined(RIJNDAEL_GENERATE_VALUES_MACRO) | 
| - | 
| -/* | 
| - * Galois field GF(2**8) multipliers, in macro form | 
| - */ | 
| -#define GFM01(a) \ | 
| -    (a)                                 /* a * 01 = a, the identity */ | 
| -#define GFM02(a) \ | 
| -    (XTIME(a) & 0xff)                   /* a * 02 = xtime(a) */ | 
| -#define GFM04(a) \ | 
| -    (GFM02(GFM02(a)))                   /* a * 04 = xtime**2(a) */ | 
| -#define GFM08(a) \ | 
| -    (GFM02(GFM04(a)))                   /* a * 08 = xtime**3(a) */ | 
| -#define GFM03(a) \ | 
| -    (GFM01(a) ^ GFM02(a))               /* a * 03 = a * (01 + 02) */ | 
| -#define GFM09(a) \ | 
| -    (GFM01(a) ^ GFM08(a))               /* a * 09 = a * (01 + 08) */ | 
| -#define GFM0B(a) \ | 
| -    (GFM01(a) ^ GFM02(a) ^ GFM08(a))    /* a * 0B = a * (01 + 02 + 08) */ | 
| -#define GFM0D(a) \ | 
| -    (GFM01(a) ^ GFM04(a) ^ GFM08(a))    /* a * 0D = a * (01 + 04 + 08) */ | 
| -#define GFM0E(a) \ | 
| -    (GFM02(a) ^ GFM04(a) ^ GFM08(a))    /* a * 0E = a * (02 + 04 + 08) */ | 
| - | 
| -#else  /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_VALUES */ | 
| - | 
| -/* GF_MULTIPLY | 
| - * | 
| - * multiply two bytes represented in GF(2**8), mod (x**4 + 1) | 
| - */ | 
| -PRUint8 gfm(PRUint8 a, PRUint8 b) | 
| -{ | 
| -    PRUint8 res = 0; | 
| -    while (b > 0) { | 
| -	res = (b & 0x01) ? res ^ a : res; | 
| -	a = XTIME(a); | 
| -	b >>= 1; | 
| -    } | 
| -    return res; | 
| -} | 
| - | 
| -#define GFM01(a) \ | 
| -    (a)                                 /* a * 01 = a, the identity */ | 
| -#define GFM02(a) \ | 
| -    (XTIME(a) & 0xff)                   /* a * 02 = xtime(a) */ | 
| -#define GFM03(a) \ | 
| -    (gfm(a, 0x03))                      /* a * 03 */ | 
| -#define GFM09(a) \ | 
| -    (gfm(a, 0x09))                      /* a * 09 */ | 
| -#define GFM0B(a) \ | 
| -    (gfm(a, 0x0B))                      /* a * 0B */ | 
| -#define GFM0D(a) \ | 
| -    (gfm(a, 0x0D))                      /* a * 0D */ | 
| -#define GFM0E(a) \ | 
| -    (gfm(a, 0x0E))                      /* a * 0E */ | 
| - | 
| -#endif /* choosing GFM function */ | 
| - | 
| -/* | 
| - * The T-tables | 
| - */ | 
| -#define G_T0(i) \ | 
| -    ( WORD4( GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)) ) ) | 
| -#define G_T1(i) \ | 
| -    ( WORD4( GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)), GFM01(SBOX(i)) ) ) | 
| -#define G_T2(i) \ | 
| -    ( WORD4( GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)), GFM01(SBOX(i)) ) ) | 
| -#define G_T3(i) \ | 
| -    ( WORD4( GFM01(SBOX(i)), GFM01(SBOX(i)), GFM03(SBOX(i)), GFM02(SBOX(i)) ) ) | 
| - | 
| -/* | 
| - * The inverse T-tables | 
| - */ | 
| -#define G_TInv0(i) \ | 
| -    ( WORD4( GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)) ) ) | 
| -#define G_TInv1(i) \ | 
| -    ( WORD4( GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)), GFM0D(SINV(i)) ) ) | 
| -#define G_TInv2(i) \ | 
| -    ( WORD4( GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)), GFM09(SINV(i)) ) ) | 
| -#define G_TInv3(i) \ | 
| -    ( WORD4( GFM09(SINV(i)), GFM0D(SINV(i)), GFM0B(SINV(i)), GFM0E(SINV(i)) ) ) | 
| - | 
| -/* | 
| - * The inverse mix column tables | 
| - */ | 
| -#define G_IMXC0(i) \ | 
| -    ( WORD4( GFM0E(i), GFM09(i), GFM0D(i), GFM0B(i) ) ) | 
| -#define G_IMXC1(i) \ | 
| -    ( WORD4( GFM0B(i), GFM0E(i), GFM09(i), GFM0D(i) ) ) | 
| -#define G_IMXC2(i) \ | 
| -    ( WORD4( GFM0D(i), GFM0B(i), GFM0E(i), GFM09(i) ) ) | 
| -#define G_IMXC3(i) \ | 
| -    ( WORD4( GFM09(i), GFM0D(i), GFM0B(i), GFM0E(i) ) ) | 
| - | 
| -/* Now choose the T-table indexing method */ | 
| -#if defined(RIJNDAEL_GENERATE_VALUES) | 
| -/* generate values for the tables with a function*/ | 
| -static PRUint32 gen_TInvXi(PRUint8 tx, PRUint8 i) | 
| -{ | 
| -    PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E; | 
| -    si01 = SINV(i); | 
| -    si02 = XTIME(si01); | 
| -    si04 = XTIME(si02); | 
| -    si08 = XTIME(si04); | 
| -    si03 = si02 ^ si01; | 
| -    si09 = si08 ^ si01; | 
| -    si0B = si08 ^ si03; | 
| -    si0D = si09 ^ si04; | 
| -    si0E = si08 ^ si04 ^ si02; | 
| -    switch (tx) { | 
| -    case 0: | 
| -	return WORD4(si0E, si09, si0D, si0B); | 
| -    case 1: | 
| -	return WORD4(si0B, si0E, si09, si0D); | 
| -    case 2: | 
| -	return WORD4(si0D, si0B, si0E, si09); | 
| -    case 3: | 
| -	return WORD4(si09, si0D, si0B, si0E); | 
| -    } | 
| -    return -1; | 
| -} | 
| -#define T0(i)    G_T0(i) | 
| -#define T1(i)    G_T1(i) | 
| -#define T2(i)    G_T2(i) | 
| -#define T3(i)    G_T3(i) | 
| -#define TInv0(i) gen_TInvXi(0, i) | 
| -#define TInv1(i) gen_TInvXi(1, i) | 
| -#define TInv2(i) gen_TInvXi(2, i) | 
| -#define TInv3(i) gen_TInvXi(3, i) | 
| -#define IMXC0(b) G_IMXC0(b) | 
| -#define IMXC1(b) G_IMXC1(b) | 
| -#define IMXC2(b) G_IMXC2(b) | 
| -#define IMXC3(b) G_IMXC3(b) | 
| -#elif defined(RIJNDAEL_GENERATE_VALUES_MACRO) | 
| -/* generate values for the tables with macros */ | 
| -#define T0(i)    G_T0(i) | 
| -#define T1(i)    G_T1(i) | 
| -#define T2(i)    G_T2(i) | 
| -#define T3(i)    G_T3(i) | 
| -#define TInv0(i) G_TInv0(i) | 
| -#define TInv1(i) G_TInv1(i) | 
| -#define TInv2(i) G_TInv2(i) | 
| -#define TInv3(i) G_TInv3(i) | 
| -#define IMXC0(b) G_IMXC0(b) | 
| -#define IMXC1(b) G_IMXC1(b) | 
| -#define IMXC2(b) G_IMXC2(b) | 
| -#define IMXC3(b) G_IMXC3(b) | 
| -#else  /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_TABLES_MACRO */ | 
| -/* Generate T and T**-1 table values and store, then index */ | 
| -/* The inverse mix column tables are still generated */ | 
| -#define T0(i)    rijndaelTables->T0[i] | 
| -#define T1(i)    rijndaelTables->T1[i] | 
| -#define T2(i)    rijndaelTables->T2[i] | 
| -#define T3(i)    rijndaelTables->T3[i] | 
| -#define TInv0(i) rijndaelTables->TInv0[i] | 
| -#define TInv1(i) rijndaelTables->TInv1[i] | 
| -#define TInv2(i) rijndaelTables->TInv2[i] | 
| -#define TInv3(i) rijndaelTables->TInv3[i] | 
| -#define IMXC0(b) G_IMXC0(b) | 
| -#define IMXC1(b) G_IMXC1(b) | 
| -#define IMXC2(b) G_IMXC2(b) | 
| -#define IMXC3(b) G_IMXC3(b) | 
| -#endif /* choose T-table indexing method */ | 
| - | 
| -#endif /* not RIJNDAEL_INCLUDE_TABLES */ | 
| - | 
| -#if defined(RIJNDAEL_GENERATE_TABLES) ||  \ | 
| -    defined(RIJNDAEL_GENERATE_TABLES_MACRO) | 
| - | 
| -/* Code to generate and store the tables */ | 
| - | 
| -struct rijndael_tables_str { | 
| -    PRUint32 T0[256]; | 
| -    PRUint32 T1[256]; | 
| -    PRUint32 T2[256]; | 
| -    PRUint32 T3[256]; | 
| -    PRUint32 TInv0[256]; | 
| -    PRUint32 TInv1[256]; | 
| -    PRUint32 TInv2[256]; | 
| -    PRUint32 TInv3[256]; | 
| -}; | 
| - | 
| -static struct rijndael_tables_str *rijndaelTables = NULL; | 
| -static PRCallOnceType coRTInit = { 0, 0, 0 }; | 
| -static PRStatus | 
| -init_rijndael_tables(void) | 
| -{ | 
| -    PRUint32 i; | 
| -    PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E; | 
| -    struct rijndael_tables_str *rts; | 
| -    rts = (struct rijndael_tables_str *) | 
| -                   PORT_Alloc(sizeof(struct rijndael_tables_str)); | 
| -    if (!rts) return PR_FAILURE; | 
| -    for (i=0; i<256; i++) { | 
| -	/* The forward values */ | 
| -	si01 = SBOX(i); | 
| -	si02 = XTIME(si01); | 
| -	si03 = si02 ^ si01; | 
| -	rts->T0[i] = WORD4(si02, si01, si01, si03); | 
| -	rts->T1[i] = WORD4(si03, si02, si01, si01); | 
| -	rts->T2[i] = WORD4(si01, si03, si02, si01); | 
| -	rts->T3[i] = WORD4(si01, si01, si03, si02); | 
| -	/* The inverse values */ | 
| -	si01 = SINV(i); | 
| -	si02 = XTIME(si01); | 
| -	si04 = XTIME(si02); | 
| -	si08 = XTIME(si04); | 
| -	si03 = si02 ^ si01; | 
| -	si09 = si08 ^ si01; | 
| -	si0B = si08 ^ si03; | 
| -	si0D = si09 ^ si04; | 
| -	si0E = si08 ^ si04 ^ si02; | 
| -	rts->TInv0[i] = WORD4(si0E, si09, si0D, si0B); | 
| -	rts->TInv1[i] = WORD4(si0B, si0E, si09, si0D); | 
| -	rts->TInv2[i] = WORD4(si0D, si0B, si0E, si09); | 
| -	rts->TInv3[i] = WORD4(si09, si0D, si0B, si0E); | 
| -    } | 
| -    /* wait until all the values are in to set */ | 
| -    rijndaelTables = rts; | 
| -    return PR_SUCCESS; | 
| -} | 
| - | 
| -#endif /* code to generate tables */ | 
| - | 
| -/************************************************************************** | 
| - * | 
| - * Stuff related to the Rijndael key schedule | 
| - * | 
| - *************************************************************************/ | 
| - | 
| -#define SUBBYTE(w) \ | 
| -    ((SBOX((w >> 24) & 0xff) << 24) | \ | 
| -     (SBOX((w >> 16) & 0xff) << 16) | \ | 
| -     (SBOX((w >>  8) & 0xff) <<  8) | \ | 
| -     (SBOX((w      ) & 0xff)         )) | 
| - | 
| -#ifdef IS_LITTLE_ENDIAN | 
| -#define ROTBYTE(b) \ | 
| -    ((b >> 8) | (b << 24)) | 
| -#else | 
| -#define ROTBYTE(b) \ | 
| -    ((b << 8) | (b >> 24)) | 
| -#endif | 
| - | 
| -/* rijndael_key_expansion7 | 
| - * | 
| - * Generate the expanded key from the key input by the user. | 
| - * XXX | 
| - * Nk == 7 (224 key bits) is a weird case.  Since Nk > 6, an added SubByte | 
| - * transformation is done periodically.  The period is every 4 bytes, and | 
| - * since 7%4 != 0 this happens at different times for each key word (unlike | 
| - * Nk == 8 where it happens twice in every key word, in the same positions). | 
| - * For now, I'm implementing this case "dumbly", w/o any unrolling. | 
| - */ | 
| -static SECStatus | 
| -rijndael_key_expansion7(AESContext *cx, const unsigned char *key, unsigned int Nk) | 
| -{ | 
| -    unsigned int i; | 
| -    PRUint32 *W; | 
| -    PRUint32 *pW; | 
| -    PRUint32 tmp; | 
| -    W = cx->expandedKey; | 
| -    /* 1.  the first Nk words contain the cipher key */ | 
| -    memcpy(W, key, Nk * 4); | 
| -    i = Nk; | 
| -    /* 2.  loop until full expanded key is obtained */ | 
| -    pW = W + i - 1; | 
| -    for (; i < cx->Nb * (cx->Nr + 1); ++i) { | 
| -	tmp = *pW++; | 
| -	if (i % Nk == 0) | 
| -	    tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1]; | 
| -	else if (i % Nk == 4) | 
| -	    tmp = SUBBYTE(tmp); | 
| -	*pW = W[i - Nk] ^ tmp; | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -/* rijndael_key_expansion | 
| - * | 
| - * Generate the expanded key from the key input by the user. | 
| - */ | 
| -static SECStatus | 
| -rijndael_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk) | 
| -{ | 
| -    unsigned int i; | 
| -    PRUint32 *W; | 
| -    PRUint32 *pW; | 
| -    PRUint32 tmp; | 
| -    unsigned int round_key_words = cx->Nb * (cx->Nr + 1); | 
| -    if (Nk == 7) | 
| -	return rijndael_key_expansion7(cx, key, Nk); | 
| -    W = cx->expandedKey; | 
| -    /* The first Nk words contain the input cipher key */ | 
| -    memcpy(W, key, Nk * 4); | 
| -    i = Nk; | 
| -    pW = W + i - 1; | 
| -    /* Loop over all sets of Nk words, except the last */ | 
| -    while (i < round_key_words - Nk) { | 
| -	tmp = *pW++; | 
| -	tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1]; | 
| -	*pW = W[i++ - Nk] ^ tmp; | 
| -	tmp = *pW++; *pW = W[i++ - Nk] ^ tmp; | 
| -	tmp = *pW++; *pW = W[i++ - Nk] ^ tmp; | 
| -	tmp = *pW++; *pW = W[i++ - Nk] ^ tmp; | 
| -	if (Nk == 4) | 
| -	    continue; | 
| -	switch (Nk) { | 
| -	case 8: tmp = *pW++; tmp = SUBBYTE(tmp); *pW = W[i++ - Nk] ^ tmp; | 
| -	case 7: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp; | 
| -	case 6: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp; | 
| -	case 5: tmp = *pW++; *pW = W[i++ - Nk] ^ tmp; | 
| -	} | 
| -    } | 
| -    /* Generate the last word */ | 
| -    tmp = *pW++; | 
| -    tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1]; | 
| -    *pW = W[i++ - Nk] ^ tmp; | 
| -    /* There may be overflow here, if Nk % (Nb * (Nr + 1)) > 0.  However, | 
| -     * since the above loop generated all but the last Nk key words, there | 
| -     * is no more need for the SubByte transformation. | 
| -     */ | 
| -    if (Nk < 8) { | 
| -	for (; i < round_key_words; ++i) { | 
| -	    tmp = *pW++; | 
| -	    *pW = W[i - Nk] ^ tmp; | 
| -	} | 
| -    } else { | 
| -	/* except in the case when Nk == 8.  Then one more SubByte may have | 
| -	 * to be performed, at i % Nk == 4. | 
| -	 */ | 
| -	for (; i < round_key_words; ++i) { | 
| -	    tmp = *pW++; | 
| -	    if (i % Nk == 4) | 
| -		tmp = SUBBYTE(tmp); | 
| -	    *pW = W[i - Nk] ^ tmp; | 
| -	} | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -/* rijndael_invkey_expansion | 
| - * | 
| - * Generate the expanded key for the inverse cipher from the key input by | 
| - * the user. | 
| - */ | 
| -static SECStatus | 
| -rijndael_invkey_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk) | 
| -{ | 
| -    unsigned int r; | 
| -    PRUint32 *roundkeyw; | 
| -    PRUint8 *b; | 
| -    int Nb = cx->Nb; | 
| -    /* begins like usual key expansion ... */ | 
| -    if (rijndael_key_expansion(cx, key, Nk) != SECSuccess) | 
| -	return SECFailure; | 
| -    /* ... but has the additional step of InvMixColumn, | 
| -     * excepting the first and last round keys. | 
| -     */ | 
| -    roundkeyw = cx->expandedKey + cx->Nb; | 
| -    for (r=1; r<cx->Nr; ++r) { | 
| -	/* each key word, roundkeyw, represents a column in the key | 
| -	 * matrix.  Each column is multiplied by the InvMixColumn matrix. | 
| -	 *   [ 0E 0B 0D 09 ]   [ b0 ] | 
| -	 *   [ 09 0E 0B 0D ] * [ b1 ] | 
| -	 *   [ 0D 09 0E 0B ]   [ b2 ] | 
| -	 *   [ 0B 0D 09 0E ]   [ b3 ] | 
| -	 */ | 
| -	b = (PRUint8 *)roundkeyw; | 
| -	*roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]); | 
| -	b = (PRUint8 *)roundkeyw; | 
| -	*roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]); | 
| -	b = (PRUint8 *)roundkeyw; | 
| -	*roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]); | 
| -	b = (PRUint8 *)roundkeyw; | 
| -	*roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ IMXC2(b[2]) ^ IMXC3(b[3]); | 
| -	if (Nb <= 4) | 
| -	    continue; | 
| -	switch (Nb) { | 
| -	case 8: b = (PRUint8 *)roundkeyw; | 
| -	        *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ | 
| -	                       IMXC2(b[2]) ^ IMXC3(b[3]); | 
| -	case 7: b = (PRUint8 *)roundkeyw; | 
| -	        *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ | 
| -	                       IMXC2(b[2]) ^ IMXC3(b[3]); | 
| -	case 6: b = (PRUint8 *)roundkeyw; | 
| -	        *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ | 
| -	                       IMXC2(b[2]) ^ IMXC3(b[3]); | 
| -	case 5: b = (PRUint8 *)roundkeyw; | 
| -	        *roundkeyw++ = IMXC0(b[0]) ^ IMXC1(b[1]) ^ | 
| -	                       IMXC2(b[2]) ^ IMXC3(b[3]); | 
| -	} | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| -/************************************************************************** | 
| - * | 
| - * Stuff related to Rijndael encryption/decryption, optimized for | 
| - * a 128-bit blocksize. | 
| - * | 
| - *************************************************************************/ | 
| - | 
| -#ifdef IS_LITTLE_ENDIAN | 
| -#define BYTE0WORD(w) ((w) & 0x000000ff) | 
| -#define BYTE1WORD(w) ((w) & 0x0000ff00) | 
| -#define BYTE2WORD(w) ((w) & 0x00ff0000) | 
| -#define BYTE3WORD(w) ((w) & 0xff000000) | 
| -#else | 
| -#define BYTE0WORD(w) ((w) & 0xff000000) | 
| -#define BYTE1WORD(w) ((w) & 0x00ff0000) | 
| -#define BYTE2WORD(w) ((w) & 0x0000ff00) | 
| -#define BYTE3WORD(w) ((w) & 0x000000ff) | 
| -#endif | 
| - | 
| -typedef union { | 
| -    PRUint32 w[4]; | 
| -    PRUint8  b[16]; | 
| -} rijndael_state; | 
| - | 
| -#define COLUMN_0(state) state.w[0] | 
| -#define COLUMN_1(state) state.w[1] | 
| -#define COLUMN_2(state) state.w[2] | 
| -#define COLUMN_3(state) state.w[3] | 
| - | 
| -#define STATE_BYTE(i) state.b[i] | 
| - | 
| -static SECStatus | 
| -rijndael_encryptBlock128(AESContext *cx, | 
| -                         unsigned char *output, | 
| -                         const unsigned char *input) | 
| -{ | 
| -    unsigned int r; | 
| -    PRUint32 *roundkeyw; | 
| -    rijndael_state state; | 
| -    PRUint32 C0, C1, C2, C3; | 
| -#if defined(NSS_X86_OR_X64) | 
| -#define pIn input | 
| -#define pOut output | 
| -#else | 
| -    unsigned char *pIn, *pOut; | 
| -    PRUint32 inBuf[4], outBuf[4]; | 
| - | 
| -    if ((ptrdiff_t)input & 0x3) { | 
| -	memcpy(inBuf, input, sizeof inBuf); | 
| -	pIn = (unsigned char *)inBuf; | 
| -    } else { | 
| -	pIn = (unsigned char *)input; | 
| -    } | 
| -    if ((ptrdiff_t)output & 0x3) { | 
| -	pOut = (unsigned char *)outBuf; | 
| -    } else { | 
| -	pOut = (unsigned char *)output; | 
| -    } | 
| -#endif | 
| -    roundkeyw = cx->expandedKey; | 
| -    /* Step 1: Add Round Key 0 to initial state */ | 
| -    COLUMN_0(state) = *((PRUint32 *)(pIn     )) ^ *roundkeyw++; | 
| -    COLUMN_1(state) = *((PRUint32 *)(pIn + 4 )) ^ *roundkeyw++; | 
| -    COLUMN_2(state) = *((PRUint32 *)(pIn + 8 )) ^ *roundkeyw++; | 
| -    COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw++; | 
| -    /* Step 2: Loop over rounds [1..NR-1] */ | 
| -    for (r=1; r<cx->Nr; ++r) { | 
| -        /* Do ShiftRow, ByteSub, and MixColumn all at once */ | 
| -	C0 = T0(STATE_BYTE(0))  ^ | 
| -	     T1(STATE_BYTE(5))  ^ | 
| -	     T2(STATE_BYTE(10)) ^ | 
| -	     T3(STATE_BYTE(15)); | 
| -	C1 = T0(STATE_BYTE(4))  ^ | 
| -	     T1(STATE_BYTE(9))  ^ | 
| -	     T2(STATE_BYTE(14)) ^ | 
| -	     T3(STATE_BYTE(3)); | 
| -	C2 = T0(STATE_BYTE(8))  ^ | 
| -	     T1(STATE_BYTE(13)) ^ | 
| -	     T2(STATE_BYTE(2))  ^ | 
| -	     T3(STATE_BYTE(7)); | 
| -	C3 = T0(STATE_BYTE(12)) ^ | 
| -	     T1(STATE_BYTE(1))  ^ | 
| -	     T2(STATE_BYTE(6))  ^ | 
| -	     T3(STATE_BYTE(11)); | 
| -	/* Round key addition */ | 
| -	COLUMN_0(state) = C0 ^ *roundkeyw++; | 
| -	COLUMN_1(state) = C1 ^ *roundkeyw++; | 
| -	COLUMN_2(state) = C2 ^ *roundkeyw++; | 
| -	COLUMN_3(state) = C3 ^ *roundkeyw++; | 
| -    } | 
| -    /* Step 3: Do the last round */ | 
| -    /* Final round does not employ MixColumn */ | 
| -    C0 = ((BYTE0WORD(T2(STATE_BYTE(0))))   | | 
| -          (BYTE1WORD(T3(STATE_BYTE(5))))   | | 
| -          (BYTE2WORD(T0(STATE_BYTE(10))))  | | 
| -          (BYTE3WORD(T1(STATE_BYTE(15)))))  ^ | 
| -          *roundkeyw++; | 
| -    C1 = ((BYTE0WORD(T2(STATE_BYTE(4))))   | | 
| -          (BYTE1WORD(T3(STATE_BYTE(9))))   | | 
| -          (BYTE2WORD(T0(STATE_BYTE(14))))  | | 
| -          (BYTE3WORD(T1(STATE_BYTE(3)))))   ^ | 
| -          *roundkeyw++; | 
| -    C2 = ((BYTE0WORD(T2(STATE_BYTE(8))))   | | 
| -          (BYTE1WORD(T3(STATE_BYTE(13))))  | | 
| -          (BYTE2WORD(T0(STATE_BYTE(2))))   | | 
| -          (BYTE3WORD(T1(STATE_BYTE(7)))))   ^ | 
| -          *roundkeyw++; | 
| -    C3 = ((BYTE0WORD(T2(STATE_BYTE(12))))  | | 
| -          (BYTE1WORD(T3(STATE_BYTE(1))))   | | 
| -          (BYTE2WORD(T0(STATE_BYTE(6))))   | | 
| -          (BYTE3WORD(T1(STATE_BYTE(11)))))  ^ | 
| -          *roundkeyw++; | 
| -    *((PRUint32 *) pOut     )  = C0; | 
| -    *((PRUint32 *)(pOut + 4))  = C1; | 
| -    *((PRUint32 *)(pOut + 8))  = C2; | 
| -    *((PRUint32 *)(pOut + 12)) = C3; | 
| -#if defined(NSS_X86_OR_X64) | 
| -#undef pIn | 
| -#undef pOut | 
| -#else | 
| -    if ((ptrdiff_t)output & 0x3) { | 
| -	memcpy(output, outBuf, sizeof outBuf); | 
| -    } | 
| -#endif | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -static SECStatus | 
| -rijndael_decryptBlock128(AESContext *cx, | 
| -                         unsigned char *output, | 
| -                         const unsigned char *input) | 
| -{ | 
| -    int r; | 
| -    PRUint32 *roundkeyw; | 
| -    rijndael_state state; | 
| -    PRUint32 C0, C1, C2, C3; | 
| -#if defined(NSS_X86_OR_X64) | 
| -#define pIn input | 
| -#define pOut output | 
| -#else | 
| -    unsigned char *pIn, *pOut; | 
| -    PRUint32 inBuf[4], outBuf[4]; | 
| - | 
| -    if ((ptrdiff_t)input & 0x3) { | 
| -	memcpy(inBuf, input, sizeof inBuf); | 
| -	pIn = (unsigned char *)inBuf; | 
| -    } else { | 
| -	pIn = (unsigned char *)input; | 
| -    } | 
| -    if ((ptrdiff_t)output & 0x3) { | 
| -	pOut = (unsigned char *)outBuf; | 
| -    } else { | 
| -	pOut = (unsigned char *)output; | 
| -    } | 
| -#endif | 
| -    roundkeyw = cx->expandedKey + cx->Nb * cx->Nr + 3; | 
| -    /* reverse the final key addition */ | 
| -    COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw--; | 
| -    COLUMN_2(state) = *((PRUint32 *)(pIn +  8)) ^ *roundkeyw--; | 
| -    COLUMN_1(state) = *((PRUint32 *)(pIn +  4)) ^ *roundkeyw--; | 
| -    COLUMN_0(state) = *((PRUint32 *)(pIn     )) ^ *roundkeyw--; | 
| -    /* Loop over rounds in reverse [NR..1] */ | 
| -    for (r=cx->Nr; r>1; --r) { | 
| -	/* Invert the (InvByteSub*InvMixColumn)(InvShiftRow(state)) */ | 
| -	C0 = TInv0(STATE_BYTE(0))  ^ | 
| -	     TInv1(STATE_BYTE(13)) ^ | 
| -	     TInv2(STATE_BYTE(10)) ^ | 
| -	     TInv3(STATE_BYTE(7)); | 
| -	C1 = TInv0(STATE_BYTE(4))  ^ | 
| -	     TInv1(STATE_BYTE(1))  ^ | 
| -	     TInv2(STATE_BYTE(14)) ^ | 
| -	     TInv3(STATE_BYTE(11)); | 
| -	C2 = TInv0(STATE_BYTE(8))  ^ | 
| -	     TInv1(STATE_BYTE(5))  ^ | 
| -	     TInv2(STATE_BYTE(2))  ^ | 
| -	     TInv3(STATE_BYTE(15)); | 
| -	C3 = TInv0(STATE_BYTE(12)) ^ | 
| -	     TInv1(STATE_BYTE(9))  ^ | 
| -	     TInv2(STATE_BYTE(6))  ^ | 
| -	     TInv3(STATE_BYTE(3)); | 
| -	/* Invert the key addition step */ | 
| -	COLUMN_3(state) = C3 ^ *roundkeyw--; | 
| -	COLUMN_2(state) = C2 ^ *roundkeyw--; | 
| -	COLUMN_1(state) = C1 ^ *roundkeyw--; | 
| -	COLUMN_0(state) = C0 ^ *roundkeyw--; | 
| -    } | 
| -    /* inverse sub */ | 
| -    pOut[ 0] = SINV(STATE_BYTE( 0)); | 
| -    pOut[ 1] = SINV(STATE_BYTE(13)); | 
| -    pOut[ 2] = SINV(STATE_BYTE(10)); | 
| -    pOut[ 3] = SINV(STATE_BYTE( 7)); | 
| -    pOut[ 4] = SINV(STATE_BYTE( 4)); | 
| -    pOut[ 5] = SINV(STATE_BYTE( 1)); | 
| -    pOut[ 6] = SINV(STATE_BYTE(14)); | 
| -    pOut[ 7] = SINV(STATE_BYTE(11)); | 
| -    pOut[ 8] = SINV(STATE_BYTE( 8)); | 
| -    pOut[ 9] = SINV(STATE_BYTE( 5)); | 
| -    pOut[10] = SINV(STATE_BYTE( 2)); | 
| -    pOut[11] = SINV(STATE_BYTE(15)); | 
| -    pOut[12] = SINV(STATE_BYTE(12)); | 
| -    pOut[13] = SINV(STATE_BYTE( 9)); | 
| -    pOut[14] = SINV(STATE_BYTE( 6)); | 
| -    pOut[15] = SINV(STATE_BYTE( 3)); | 
| -    /* final key addition */ | 
| -    *((PRUint32 *)(pOut + 12)) ^= *roundkeyw--; | 
| -    *((PRUint32 *)(pOut +  8)) ^= *roundkeyw--; | 
| -    *((PRUint32 *)(pOut +  4)) ^= *roundkeyw--; | 
| -    *((PRUint32 *) pOut      ) ^= *roundkeyw--; | 
| -#if defined(NSS_X86_OR_X64) | 
| -#undef pIn | 
| -#undef pOut | 
| -#else | 
| -    if ((ptrdiff_t)output & 0x3) { | 
| -	memcpy(output, outBuf, sizeof outBuf); | 
| -    } | 
| -#endif | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -/************************************************************************** | 
| - * | 
| - * Stuff related to general Rijndael encryption/decryption, for blocksizes | 
| - * greater than 128 bits. | 
| - * | 
| - * XXX This code is currently untested!  So far, AES specs have only been | 
| - *     released for 128 bit blocksizes.  This will be tested, but for now | 
| - *     only the code above has been tested using known values. | 
| - * | 
| - *************************************************************************/ | 
| - | 
| -#define COLUMN(array, j) *((PRUint32 *)(array + j)) | 
| - | 
| -SECStatus | 
| -rijndael_encryptBlock(AESContext *cx, | 
| -                      unsigned char *output, | 
| -                      const unsigned char *input) | 
| -{ | 
| -    return SECFailure; | 
| -#ifdef rijndael_large_blocks_fixed | 
| -    unsigned int j, r, Nb; | 
| -    unsigned int c2=0, c3=0; | 
| -    PRUint32 *roundkeyw; | 
| -    PRUint8 clone[RIJNDAEL_MAX_STATE_SIZE]; | 
| -    Nb = cx->Nb; | 
| -    roundkeyw = cx->expandedKey; | 
| -    /* Step 1: Add Round Key 0 to initial state */ | 
| -    for (j=0; j<4*Nb; j+=4) { | 
| -	COLUMN(clone, j) = COLUMN(input, j) ^ *roundkeyw++; | 
| -    } | 
| -    /* Step 2: Loop over rounds [1..NR-1] */ | 
| -    for (r=1; r<cx->Nr; ++r) { | 
| -	for (j=0; j<Nb; ++j) { | 
| -	    COLUMN(output, j) = T0(STATE_BYTE(4*  j          )) ^ | 
| -	                        T1(STATE_BYTE(4*((j+ 1)%Nb)+1)) ^ | 
| -	                        T2(STATE_BYTE(4*((j+c2)%Nb)+2)) ^ | 
| -	                        T3(STATE_BYTE(4*((j+c3)%Nb)+3)); | 
| -	} | 
| -	for (j=0; j<4*Nb; j+=4) { | 
| -	    COLUMN(clone, j) = COLUMN(output, j) ^ *roundkeyw++; | 
| -	} | 
| -    } | 
| -    /* Step 3: Do the last round */ | 
| -    /* Final round does not employ MixColumn */ | 
| -    for (j=0; j<Nb; ++j) { | 
| -	COLUMN(output, j) = ((BYTE0WORD(T2(STATE_BYTE(4* j         ))))  | | 
| -                             (BYTE1WORD(T3(STATE_BYTE(4*(j+ 1)%Nb)+1)))  | | 
| -                             (BYTE2WORD(T0(STATE_BYTE(4*(j+c2)%Nb)+2)))  | | 
| -                             (BYTE3WORD(T1(STATE_BYTE(4*(j+c3)%Nb)+3)))) ^ | 
| -	                     *roundkeyw++; | 
| -    } | 
| -    return SECSuccess; | 
| -#endif | 
| -} | 
| - | 
| -SECStatus | 
| -rijndael_decryptBlock(AESContext *cx, | 
| -                      unsigned char *output, | 
| -                      const unsigned char *input) | 
| -{ | 
| -    return SECFailure; | 
| -#ifdef rijndael_large_blocks_fixed | 
| -    int j, r, Nb; | 
| -    int c2=0, c3=0; | 
| -    PRUint32 *roundkeyw; | 
| -    PRUint8 clone[RIJNDAEL_MAX_STATE_SIZE]; | 
| -    Nb = cx->Nb; | 
| -    roundkeyw = cx->expandedKey + cx->Nb * cx->Nr + 3; | 
| -    /* reverse key addition */ | 
| -    for (j=4*Nb; j>=0; j-=4) { | 
| -	COLUMN(clone, j) = COLUMN(input, j) ^ *roundkeyw--; | 
| -    } | 
| -    /* Loop over rounds in reverse [NR..1] */ | 
| -    for (r=cx->Nr; r>1; --r) { | 
| -	/* Invert the (InvByteSub*InvMixColumn)(InvShiftRow(state)) */ | 
| -	for (j=0; j<Nb; ++j) { | 
| -	    COLUMN(output, 4*j) = TInv0(STATE_BYTE(4* j            )) ^ | 
| -	                          TInv1(STATE_BYTE(4*(j+Nb- 1)%Nb)+1) ^ | 
| -	                          TInv2(STATE_BYTE(4*(j+Nb-c2)%Nb)+2) ^ | 
| -	                          TInv3(STATE_BYTE(4*(j+Nb-c3)%Nb)+3); | 
| -	} | 
| -	/* Invert the key addition step */ | 
| -	for (j=4*Nb; j>=0; j-=4) { | 
| -	    COLUMN(clone, j) = COLUMN(output, j) ^ *roundkeyw--; | 
| -	} | 
| -    } | 
| -    /* inverse sub */ | 
| -    for (j=0; j<4*Nb; ++j) { | 
| -	output[j] = SINV(clone[j]); | 
| -    } | 
| -    /* final key addition */ | 
| -    for (j=4*Nb; j>=0; j-=4) { | 
| -	COLUMN(output, j) ^= *roundkeyw--; | 
| -    } | 
| -    return SECSuccess; | 
| -#endif | 
| -} | 
| - | 
| -/************************************************************************** | 
| - * | 
| - *  Rijndael modes of operation (ECB and CBC) | 
| - * | 
| - *************************************************************************/ | 
| - | 
| -static SECStatus | 
| -rijndael_encryptECB(AESContext *cx, unsigned char *output, | 
| -                    unsigned int *outputLen, unsigned int maxOutputLen, | 
| -                    const unsigned char *input, unsigned int inputLen, | 
| -                    unsigned int blocksize) | 
| -{ | 
| -    SECStatus rv; | 
| -    AESBlockFunc *encryptor; | 
| - | 
| - | 
| -    encryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE) | 
| -				  ? &rijndael_encryptBlock128 | 
| -				  : &rijndael_encryptBlock; | 
| -    while (inputLen > 0) { | 
| -        rv = (*encryptor)(cx, output, input); | 
| -	if (rv != SECSuccess) | 
| -	    return rv; | 
| -	output += blocksize; | 
| -	input += blocksize; | 
| -	inputLen -= blocksize; | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -static SECStatus | 
| -rijndael_encryptCBC(AESContext *cx, unsigned char *output, | 
| -                    unsigned int *outputLen, unsigned int maxOutputLen, | 
| -                    const unsigned char *input, unsigned int inputLen, | 
| -                    unsigned int blocksize) | 
| -{ | 
| -    unsigned int j; | 
| -    SECStatus rv; | 
| -    AESBlockFunc *encryptor; | 
| -    unsigned char *lastblock; | 
| -    unsigned char inblock[RIJNDAEL_MAX_STATE_SIZE * 8]; | 
| - | 
| -    if (!inputLen) | 
| -	return SECSuccess; | 
| -    lastblock = cx->iv; | 
| -    encryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE) | 
| -				  ? &rijndael_encryptBlock128 | 
| -				  : &rijndael_encryptBlock; | 
| -    while (inputLen > 0) { | 
| -	/* XOR with the last block (IV if first block) */ | 
| -	for (j=0; j<blocksize; ++j) | 
| -	    inblock[j] = input[j] ^ lastblock[j]; | 
| -	/* encrypt */ | 
| -        rv = (*encryptor)(cx, output, inblock); | 
| -	if (rv != SECSuccess) | 
| -	    return rv; | 
| -	/* move to the next block */ | 
| -	lastblock = output; | 
| -	output += blocksize; | 
| -	input += blocksize; | 
| -	inputLen -= blocksize; | 
| -    } | 
| -    memcpy(cx->iv, lastblock, blocksize); | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -static SECStatus | 
| -rijndael_decryptECB(AESContext *cx, unsigned char *output, | 
| -                    unsigned int *outputLen, unsigned int maxOutputLen, | 
| -                    const unsigned char *input, unsigned int inputLen, | 
| -                    unsigned int blocksize) | 
| -{ | 
| -    SECStatus rv; | 
| -    AESBlockFunc *decryptor; | 
| - | 
| -    decryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE) | 
| -				  ? &rijndael_decryptBlock128 | 
| -				  : &rijndael_decryptBlock; | 
| -    while (inputLen > 0) { | 
| -        rv = (*decryptor)(cx, output, input); | 
| -	if (rv != SECSuccess) | 
| -	    return rv; | 
| -	output += blocksize; | 
| -	input += blocksize; | 
| -	inputLen -= blocksize; | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -static SECStatus | 
| -rijndael_decryptCBC(AESContext *cx, unsigned char *output, | 
| -                    unsigned int *outputLen, unsigned int maxOutputLen, | 
| -                    const unsigned char *input, unsigned int inputLen, | 
| -                    unsigned int blocksize) | 
| -{ | 
| -    SECStatus rv; | 
| -    AESBlockFunc *decryptor; | 
| -    const unsigned char *in; | 
| -    unsigned char *out; | 
| -    unsigned int j; | 
| -    unsigned char newIV[RIJNDAEL_MAX_BLOCKSIZE]; | 
| - | 
| - | 
| -    if (!inputLen) | 
| -	return SECSuccess; | 
| -    PORT_Assert(output - input >= 0 || input - output >= (int)inputLen ); | 
| -    decryptor = (blocksize == RIJNDAEL_MIN_BLOCKSIZE) | 
| -                                  ? &rijndael_decryptBlock128 | 
| -				  : &rijndael_decryptBlock; | 
| -    in  = input  + (inputLen - blocksize); | 
| -    memcpy(newIV, in, blocksize); | 
| -    out = output + (inputLen - blocksize); | 
| -    while (inputLen > blocksize) { | 
| -        rv = (*decryptor)(cx, out, in); | 
| -	if (rv != SECSuccess) | 
| -	    return rv; | 
| -	for (j=0; j<blocksize; ++j) | 
| -	    out[j] ^= in[(int)(j - blocksize)]; | 
| -	out -= blocksize; | 
| -	in -= blocksize; | 
| -	inputLen -= blocksize; | 
| -    } | 
| -    if (in == input) { | 
| -        rv = (*decryptor)(cx, out, in); | 
| -	if (rv != SECSuccess) | 
| -	    return rv; | 
| -	for (j=0; j<blocksize; ++j) | 
| -	    out[j] ^= cx->iv[j]; | 
| -    } | 
| -    memcpy(cx->iv, newIV, blocksize); | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -/************************************************************************ | 
| - * | 
| - * BLAPI Interface functions | 
| - * | 
| - * The following functions implement the encryption routines defined in | 
| - * BLAPI for the AES cipher, Rijndael. | 
| - * | 
| - ***********************************************************************/ | 
| - | 
| -AESContext * AES_AllocateContext(void) | 
| -{ | 
| -    return PORT_ZNew(AESContext); | 
| -} | 
| - | 
| - | 
| -/* | 
| -** Initialize a new AES context suitable for AES encryption/decryption in | 
| -** the ECB or CBC mode. | 
| -** 	"mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC | 
| -*/ | 
| -static SECStatus | 
| -aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, | 
| -	        const unsigned char *iv, int mode, unsigned int encrypt, | 
| -	        unsigned int blocksize) | 
| -{ | 
| -    unsigned int Nk; | 
| -    /* According to Rijndael AES Proposal, section 12.1, block and key | 
| -     * lengths between 128 and 256 bits are supported, as long as the | 
| -     * length in bytes is divisible by 4. | 
| -     */ | 
| -    if (key == NULL || | 
| -        keysize < RIJNDAEL_MIN_BLOCKSIZE   || | 
| -	keysize > RIJNDAEL_MAX_BLOCKSIZE   || | 
| -	keysize % 4 != 0 || | 
| -        blocksize < RIJNDAEL_MIN_BLOCKSIZE || | 
| -	blocksize > RIJNDAEL_MAX_BLOCKSIZE || | 
| -	blocksize % 4 != 0) { | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| -	return SECFailure; | 
| -    } | 
| -    if (mode != NSS_AES && mode != NSS_AES_CBC) { | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| -	return SECFailure; | 
| -    } | 
| -    if (mode == NSS_AES_CBC && iv == NULL) { | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| -	return SECFailure; | 
| -    } | 
| -    if (!cx) { | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| -    	return SECFailure; | 
| -    } | 
| -#if USE_HW_AES | 
| -    if (has_intel_aes == 0) { | 
| -	unsigned long eax, ebx, ecx, edx; | 
| -	char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES"); | 
| - | 
| -	if (disable_hw_aes == NULL) { | 
| -	    freebl_cpuid(1, &eax, &ebx, &ecx, &edx); | 
| -	    has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1; | 
| -	    has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1; | 
| -	    has_intel_avx = (ecx & (1 << 28)) != 0 ? 1 : -1; | 
| -	} else { | 
| -	    has_intel_aes = -1; | 
| -	    has_intel_avx = -1; | 
| -	    has_intel_clmul = -1; | 
| -	} | 
| -    } | 
| -    use_hw_aes = (PRBool) | 
| -		(has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16); | 
| -    use_hw_gcm = (PRBool) | 
| -		(use_hw_aes && has_intel_avx>0 && has_intel_clmul>0); | 
| -#endif | 
| -    /* Nb = (block size in bits) / 32 */ | 
| -    cx->Nb = blocksize / 4; | 
| -    /* Nk = (key size in bits) / 32 */ | 
| -    Nk = keysize / 4; | 
| -    /* Obtain number of rounds from "table" */ | 
| -    cx->Nr = RIJNDAEL_NUM_ROUNDS(Nk, cx->Nb); | 
| -    /* copy in the iv, if neccessary */ | 
| -    if (mode == NSS_AES_CBC) { | 
| -	memcpy(cx->iv, iv, blocksize); | 
| -#if USE_HW_AES | 
| -	if (use_hw_aes) { | 
| -	    cx->worker = (freeblCipherFunc) | 
| -				intel_aes_cbc_worker(encrypt, keysize); | 
| -	} else | 
| -#endif | 
| -	    cx->worker = (freeblCipherFunc) (encrypt | 
| -			  ? &rijndael_encryptCBC : &rijndael_decryptCBC); | 
| -    } else { | 
| -#if  USE_HW_AES | 
| -	if (use_hw_aes) { | 
| -	    cx->worker = (freeblCipherFunc) | 
| -				intel_aes_ecb_worker(encrypt, keysize); | 
| -	} else | 
| -#endif | 
| -	    cx->worker = (freeblCipherFunc) (encrypt | 
| -			  ? &rijndael_encryptECB : &rijndael_decryptECB); | 
| -    } | 
| -    PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE); | 
| -    if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) { | 
| -	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 
| -	goto cleanup; | 
| -    } | 
| -#ifdef USE_HW_AES | 
| -    if (use_hw_aes) { | 
| -	intel_aes_init(encrypt, keysize); | 
| -    } else | 
| -#endif | 
| -    { | 
| - | 
| -#if defined(RIJNDAEL_GENERATE_TABLES) ||  \ | 
| -	defined(RIJNDAEL_GENERATE_TABLES_MACRO) | 
| -	if (rijndaelTables == NULL) { | 
| -	    if (PR_CallOnce(&coRTInit, init_rijndael_tables) | 
| -	      != PR_SUCCESS) { | 
| -		return SecFailure; | 
| -	    } | 
| -	} | 
| -#endif | 
| -	/* Generate expanded key */ | 
| -	if (encrypt) { | 
| -	    if (rijndael_key_expansion(cx, key, Nk) != SECSuccess) | 
| -		goto cleanup; | 
| -	} else { | 
| -	    if (rijndael_invkey_expansion(cx, key, Nk) != SECSuccess) | 
| -		goto cleanup; | 
| -	} | 
| -    } | 
| -    cx->worker_cx = cx; | 
| -    cx->destroy = NULL; | 
| -    cx->isBlock = PR_TRUE; | 
| -    return SECSuccess; | 
| -cleanup: | 
| -    return SECFailure; | 
| -} | 
| - | 
| -SECStatus | 
| -AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, | 
| -	        const unsigned char *iv, int mode, unsigned int encrypt, | 
| -	        unsigned int blocksize) | 
| -{ | 
| -    int basemode = mode; | 
| -    PRBool baseencrypt = encrypt; | 
| -    SECStatus rv; | 
| - | 
| -    switch (mode) { | 
| -    case NSS_AES_CTS: | 
| -	basemode = NSS_AES_CBC; | 
| -	break; | 
| -    case NSS_AES_GCM: | 
| -    case NSS_AES_CTR: | 
| -	basemode = NSS_AES; | 
| -	baseencrypt = PR_TRUE; | 
| -	break; | 
| -    } | 
| -    /* make sure enough is initializes so we can safely call Destroy */ | 
| -    cx->worker_cx = NULL; | 
| -    cx->destroy = NULL; | 
| -    rv = aes_InitContext(cx, key, keysize, iv, basemode, | 
| -					baseencrypt, blocksize); | 
| -    if (rv != SECSuccess) { | 
| -	AES_DestroyContext(cx, PR_FALSE); | 
| -	return rv; | 
| -    } | 
| - | 
| -    /* finally, set up any mode specific contexts */ | 
| -    switch (mode) { | 
| -    case NSS_AES_CTS: | 
| -	cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv, blocksize); | 
| -	cx->worker = (freeblCipherFunc) | 
| -			(encrypt ?  CTS_EncryptUpdate : CTS_DecryptUpdate); | 
| -	cx->destroy = (freeblDestroyFunc) CTS_DestroyContext; | 
| -	cx->isBlock = PR_FALSE; | 
| -	break; | 
| -    case NSS_AES_GCM: | 
| -#if USE_HW_AES | 
| -	if(use_hw_gcm) { | 
| -        	cx->worker_cx = intel_AES_GCM_CreateContext(cx, cx->worker, iv, blocksize); | 
| -		cx->worker = (freeblCipherFunc) | 
| -			(encrypt ? intel_AES_GCM_EncryptUpdate : intel_AES_GCM_DecryptUpdate); | 
| -		cx->destroy = (freeblDestroyFunc) intel_AES_GCM_DestroyContext; | 
| -		cx->isBlock = PR_FALSE; | 
| -    	} else | 
| -#endif | 
| -	{ | 
| -	cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv, blocksize); | 
| -	cx->worker = (freeblCipherFunc) | 
| -			(encrypt ? GCM_EncryptUpdate : GCM_DecryptUpdate); | 
| -	cx->destroy = (freeblDestroyFunc) GCM_DestroyContext; | 
| -	cx->isBlock = PR_FALSE; | 
| -	} | 
| -	break; | 
| -    case NSS_AES_CTR: | 
| -	cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv, blocksize); | 
| -	cx->worker = (freeblCipherFunc) CTR_Update ; | 
| -	cx->destroy = (freeblDestroyFunc) CTR_DestroyContext; | 
| -	cx->isBlock = PR_FALSE; | 
| -	break; | 
| -    default: | 
| -	/* everything has already been set up by aes_InitContext, just | 
| -	 * return */ | 
| -	return SECSuccess; | 
| -    } | 
| -    /* check to see if we succeeded in getting the worker context */ | 
| -    if (cx->worker_cx == NULL) { | 
| -	/* no, just destroy the existing context */ | 
| -	cx->destroy = NULL; /* paranoia, though you can see a dozen lines */ | 
| -			    /* below that this isn't necessary */ | 
| -	AES_DestroyContext(cx, PR_FALSE); | 
| -	return SECFailure; | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -/* AES_CreateContext | 
| - * | 
| - * create a new context for Rijndael operations | 
| - */ | 
| -AESContext * | 
| -AES_CreateContext(const unsigned char *key, const unsigned char *iv, | 
| -                  int mode, int encrypt, | 
| -                  unsigned int keysize, unsigned int blocksize) | 
| -{ | 
| -    AESContext *cx = AES_AllocateContext(); | 
| -    if (cx) { | 
| -	SECStatus rv = AES_InitContext(cx, key, keysize, iv, mode, encrypt, | 
| -				       blocksize); | 
| -	if (rv != SECSuccess) { | 
| -	    AES_DestroyContext(cx, PR_TRUE); | 
| -	    cx = NULL; | 
| -	} | 
| -    } | 
| -    return cx; | 
| -} | 
| - | 
| -/* | 
| - * AES_DestroyContext | 
| - * | 
| - * Zero an AES cipher context.  If freeit is true, also free the pointer | 
| - * to the context. | 
| - */ | 
| -void | 
| -AES_DestroyContext(AESContext *cx, PRBool freeit) | 
| -{ | 
| -    if (cx->worker_cx && cx->destroy) { | 
| -	(*cx->destroy)(cx->worker_cx, PR_TRUE); | 
| -	cx->worker_cx = NULL; | 
| -	cx->destroy = NULL; | 
| -    } | 
| -    if (freeit) | 
| -	PORT_Free(cx); | 
| -} | 
| - | 
| -/* | 
| - * AES_Encrypt | 
| - * | 
| - * Encrypt an arbitrary-length buffer.  The output buffer must already be | 
| - * allocated to at least inputLen. | 
| - */ | 
| -SECStatus | 
| -AES_Encrypt(AESContext *cx, unsigned char *output, | 
| -            unsigned int *outputLen, unsigned int maxOutputLen, | 
| -            const unsigned char *input, unsigned int inputLen) | 
| -{ | 
| -    int blocksize; | 
| -    /* Check args */ | 
| -    if (cx == NULL || output == NULL || (input == NULL && inputLen != 0)) { | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| -	return SECFailure; | 
| -    } | 
| -    blocksize = 4 * cx->Nb; | 
| -    if (cx->isBlock && (inputLen % blocksize != 0)) { | 
| -	PORT_SetError(SEC_ERROR_INPUT_LEN); | 
| -	return SECFailure; | 
| -    } | 
| -    if (maxOutputLen < inputLen) { | 
| -	PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 
| -	return SECFailure; | 
| -    } | 
| -    *outputLen = inputLen; | 
| -    return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen, | 
| -                             input, inputLen, blocksize); | 
| -} | 
| - | 
| -/* | 
| - * AES_Decrypt | 
| - * | 
| - * Decrypt and arbitrary-length buffer.  The output buffer must already be | 
| - * allocated to at least inputLen. | 
| - */ | 
| -SECStatus | 
| -AES_Decrypt(AESContext *cx, unsigned char *output, | 
| -            unsigned int *outputLen, unsigned int maxOutputLen, | 
| -            const unsigned char *input, unsigned int inputLen) | 
| -{ | 
| -    int blocksize; | 
| -    /* Check args */ | 
| -    if (cx == NULL || output == NULL || (input == NULL && inputLen != 0)) { | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| -	return SECFailure; | 
| -    } | 
| -    blocksize = 4 * cx->Nb; | 
| -    if (cx->isBlock && (inputLen % blocksize != 0)) { | 
| -	PORT_SetError(SEC_ERROR_INPUT_LEN); | 
| -	return SECFailure; | 
| -    } | 
| -    if (maxOutputLen < inputLen) { | 
| -	PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 
| -	return SECFailure; | 
| -    } | 
| -    *outputLen = inputLen; | 
| -    return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen, | 
| -                             input, inputLen, blocksize); | 
| -} | 
|  |