|
|
1.1 ! root 1: /* ! 2: --------------------------------------------------------------------------- ! 3: Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. ! 4: ! 5: LICENSE TERMS ! 6: ! 7: The free distribution and use of this software in both source and binary ! 8: form is allowed (with or without changes) provided that: ! 9: ! 10: 1. distributions of this source code include the above copyright ! 11: notice, this list of conditions and the following disclaimer; ! 12: ! 13: 2. distributions in binary form include the above copyright ! 14: notice, this list of conditions and the following disclaimer ! 15: in the documentation and/or other associated materials; ! 16: ! 17: 3. the copyright holder's name is not used to endorse products ! 18: built using this software without specific written permission. ! 19: ! 20: ALTERNATIVELY, provided that this notice is retained in full, this product ! 21: may be distributed under the terms of the GNU General Public License (GPL), ! 22: in which case the provisions of the GPL apply INSTEAD OF those given above. ! 23: ! 24: DISCLAIMER ! 25: ! 26: This software is provided 'as is' with no explicit or implied warranties ! 27: in respect of its properties, including, but not limited to, correctness ! 28: and/or fitness for purpose. ! 29: --------------------------------------------------------------------------- ! 30: Issue 28/01/2004 ! 31: ! 32: This file contains the code for implementing encryption and decryption ! 33: for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It ! 34: can optionally be replaced by code written in assembler using NASM. For ! 35: further details see the file aesopt.h ! 36: */ ! 37: ! 38: #include "aesopt.h" ! 39: #include "aestab.h" ! 40: ! 41: #if defined(__cplusplus) ! 42: extern "C" ! 43: { ! 44: #endif ! 45: ! 46: #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) ! 47: #define so(y,x,c) word_out(y, c, s(x,c)) ! 48: ! 49: #if defined(ARRAYS) ! 50: #define locals(y,x) x[4],y[4] ! 51: #else ! 52: #define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 ! 53: #endif ! 54: ! 55: #define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ ! 56: s(y,2) = s(x,2); s(y,3) = s(x,3); ! 57: #define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) ! 58: #define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) ! 59: #define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) ! 60: ! 61: #if defined(ENCRYPTION) && !defined(AES_ASM) ! 62: ! 63: /* Visual C++ .Net v7.1 provides the fastest encryption code when using ! 64: Pentium optimiation with small code but this is poor for decryption ! 65: so we need to control this with the following VC++ pragmas ! 66: */ ! 67: ! 68: #if defined(_MSC_VER) ! 69: #pragma optimize( "s", on ) ! 70: #endif ! 71: ! 72: /* Given the column (c) of the output state variable, the following ! 73: macros give the input state variables which are needed in its ! 74: computation for each row (r) of the state. All the alternative ! 75: macros give the same end values but expand into different ways ! 76: of calculating these values. In particular the complex macro ! 77: used for dynamically variable block sizes is designed to expand ! 78: to a compile time constant whenever possible but will expand to ! 79: conditional clauses on some branches (I am grateful to Frank ! 80: Yellin for this construction) ! 81: */ ! 82: ! 83: #define fwd_var(x,r,c)\ ! 84: ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ ! 85: : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ ! 86: : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ ! 87: : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) ! 88: ! 89: #if defined(FT4_SET) ! 90: #undef dec_fmvars ! 91: #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) ! 92: #elif defined(FT1_SET) ! 93: #undef dec_fmvars ! 94: #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) ! 95: #else ! 96: #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) ! 97: #endif ! 98: ! 99: #if defined(FL4_SET) ! 100: #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) ! 101: #elif defined(FL1_SET) ! 102: #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) ! 103: #else ! 104: #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) ! 105: #endif ! 106: ! 107: aes_rval aes_encrypt(const unsigned char *in, ! 108: unsigned char *out, const aes_encrypt_ctx cx[1]) ! 109: { aes_32t locals(b0, b1); ! 110: const aes_32t *kp = cx->ks; ! 111: #if defined( dec_fmvars ) ! 112: dec_fmvars; /* declare variables for fwd_mcol() if needed */ ! 113: #endif ! 114: ! 115: #if defined( AES_ERR_CHK ) ! 116: if( cx->rn != 10 && cx->rn != 12 && cx->rn != 14 ) ! 117: return aes_error; ! 118: #endif ! 119: ! 120: state_in(b0, in, kp); ! 121: ! 122: #if (ENC_UNROLL == FULL) ! 123: ! 124: switch(cx->rn) ! 125: { ! 126: case 14: ! 127: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); ! 128: round(fwd_rnd, b0, b1, kp + 2 * N_COLS); ! 129: kp += 2 * N_COLS; ! 130: case 12: ! 131: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); ! 132: round(fwd_rnd, b0, b1, kp + 2 * N_COLS); ! 133: kp += 2 * N_COLS; ! 134: case 10: ! 135: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); ! 136: round(fwd_rnd, b0, b1, kp + 2 * N_COLS); ! 137: round(fwd_rnd, b1, b0, kp + 3 * N_COLS); ! 138: round(fwd_rnd, b0, b1, kp + 4 * N_COLS); ! 139: round(fwd_rnd, b1, b0, kp + 5 * N_COLS); ! 140: round(fwd_rnd, b0, b1, kp + 6 * N_COLS); ! 141: round(fwd_rnd, b1, b0, kp + 7 * N_COLS); ! 142: round(fwd_rnd, b0, b1, kp + 8 * N_COLS); ! 143: round(fwd_rnd, b1, b0, kp + 9 * N_COLS); ! 144: round(fwd_lrnd, b0, b1, kp +10 * N_COLS); ! 145: } ! 146: ! 147: #else ! 148: ! 149: #if (ENC_UNROLL == PARTIAL) ! 150: { aes_32t rnd; ! 151: for(rnd = 0; rnd < (cx->rn >> 1) - 1; ++rnd) ! 152: { ! 153: kp += N_COLS; ! 154: round(fwd_rnd, b1, b0, kp); ! 155: kp += N_COLS; ! 156: round(fwd_rnd, b0, b1, kp); ! 157: } ! 158: kp += N_COLS; ! 159: round(fwd_rnd, b1, b0, kp); ! 160: #else ! 161: { aes_32t rnd; ! 162: for(rnd = 0; rnd < cx->rn - 1; ++rnd) ! 163: { ! 164: kp += N_COLS; ! 165: round(fwd_rnd, b1, b0, kp); ! 166: l_copy(b0, b1); ! 167: } ! 168: #endif ! 169: kp += N_COLS; ! 170: round(fwd_lrnd, b0, b1, kp); ! 171: } ! 172: #endif ! 173: ! 174: state_out(out, b0); ! 175: #if defined( AES_ERR_CHK ) ! 176: return aes_good; ! 177: #endif ! 178: } ! 179: ! 180: #endif ! 181: ! 182: #if defined(DECRYPTION) && !defined(AES_ASM) ! 183: ! 184: /* Visual C++ .Net v7.1 provides the fastest encryption code when using ! 185: Pentium optimiation with small code but this is poor for decryption ! 186: so we need to control this with the following VC++ pragmas ! 187: */ ! 188: ! 189: #if defined(_MSC_VER) ! 190: #pragma optimize( "t", on ) ! 191: #endif ! 192: ! 193: /* Given the column (c) of the output state variable, the following ! 194: macros give the input state variables which are needed in its ! 195: computation for each row (r) of the state. All the alternative ! 196: macros give the same end values but expand into different ways ! 197: of calculating these values. In particular the complex macro ! 198: used for dynamically variable block sizes is designed to expand ! 199: to a compile time constant whenever possible but will expand to ! 200: conditional clauses on some branches (I am grateful to Frank ! 201: Yellin for this construction) ! 202: */ ! 203: ! 204: #define inv_var(x,r,c)\ ! 205: ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ ! 206: : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ ! 207: : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ ! 208: : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) ! 209: ! 210: #if defined(IT4_SET) ! 211: #undef dec_imvars ! 212: #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) ! 213: #elif defined(IT1_SET) ! 214: #undef dec_imvars ! 215: #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) ! 216: #else ! 217: #define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) ! 218: #endif ! 219: ! 220: #if defined(IL4_SET) ! 221: #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) ! 222: #elif defined(IL1_SET) ! 223: #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) ! 224: #else ! 225: #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) ! 226: #endif ! 227: ! 228: aes_rval aes_decrypt(const unsigned char *in, ! 229: unsigned char *out, const aes_decrypt_ctx cx[1]) ! 230: { aes_32t locals(b0, b1); ! 231: #if defined( dec_imvars ) ! 232: dec_imvars; /* declare variables for inv_mcol() if needed */ ! 233: #endif ! 234: const aes_32t *kp = cx->ks + cx->rn * N_COLS; ! 235: ! 236: #if defined( AES_ERR_CHK ) ! 237: if( cx->rn != 10 && cx->rn != 12 && cx->rn != 14 ) ! 238: return aes_error; ! 239: #endif ! 240: ! 241: state_in(b0, in, kp); ! 242: ! 243: #if (DEC_UNROLL == FULL) ! 244: ! 245: switch(cx->rn) ! 246: { ! 247: case 14: ! 248: round(inv_rnd, b1, b0, kp - 1 * N_COLS); ! 249: round(inv_rnd, b0, b1, kp - 2 * N_COLS); ! 250: kp -= 2 * N_COLS; ! 251: case 12: ! 252: round(inv_rnd, b1, b0, kp - 1 * N_COLS); ! 253: round(inv_rnd, b0, b1, kp - 2 * N_COLS); ! 254: kp -= 2 * N_COLS; ! 255: case 10: ! 256: round(inv_rnd, b1, b0, kp - 1 * N_COLS); ! 257: round(inv_rnd, b0, b1, kp - 2 * N_COLS); ! 258: round(inv_rnd, b1, b0, kp - 3 * N_COLS); ! 259: round(inv_rnd, b0, b1, kp - 4 * N_COLS); ! 260: round(inv_rnd, b1, b0, kp - 5 * N_COLS); ! 261: round(inv_rnd, b0, b1, kp - 6 * N_COLS); ! 262: round(inv_rnd, b1, b0, kp - 7 * N_COLS); ! 263: round(inv_rnd, b0, b1, kp - 8 * N_COLS); ! 264: round(inv_rnd, b1, b0, kp - 9 * N_COLS); ! 265: round(inv_lrnd, b0, b1, kp - 10 * N_COLS); ! 266: } ! 267: ! 268: #else ! 269: ! 270: #if (DEC_UNROLL == PARTIAL) ! 271: { aes_32t rnd; ! 272: for(rnd = 0; rnd < (cx->rn >> 1) - 1; ++rnd) ! 273: { ! 274: kp -= N_COLS; ! 275: round(inv_rnd, b1, b0, kp); ! 276: kp -= N_COLS; ! 277: round(inv_rnd, b0, b1, kp); ! 278: } ! 279: kp -= N_COLS; ! 280: round(inv_rnd, b1, b0, kp); ! 281: #else ! 282: { aes_32t rnd; ! 283: for(rnd = 0; rnd < cx->rn - 1; ++rnd) ! 284: { ! 285: kp -= N_COLS; ! 286: round(inv_rnd, b1, b0, kp); ! 287: l_copy(b0, b1); ! 288: } ! 289: #endif ! 290: kp -= N_COLS; ! 291: round(inv_lrnd, b0, b1, kp); ! 292: } ! 293: #endif ! 294: ! 295: state_out(out, b0); ! 296: #if defined( AES_ERR_CHK ) ! 297: return aes_good; ! 298: #endif ! 299: } ! 300: ! 301: #endif ! 302: ! 303: #if defined(__cplusplus) ! 304: } ! 305: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.