| OLD | NEW |
| (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 } | |
| OLD | NEW |