?? mks_aes.cpp
字號:
/* File: MKS_AES.cpp Contains: Mok-Kong Shen's byte-oriented AES implementation http://home.t-online.de/home/mok-kong.shen/#paper1 "Several readers of sci.crypt have verified that the package runs correctly on big-endian machines as well" Copyright: (c) 2003 by Xten Networks, Inc., all rights reserved.*//* ----------------------------------------------------------//// An AES implementation for 32-bit platforms//// Release 1.4 //// Release date: 10th October 2003//// Consisting of a principal part (this file) and a (separate) // Supplement. //// Author: Mok-Kong Shen, Munich, Germany//// Last date of site modification: (currently empty)////// Design assumptions: Size of unsigned int 32 bits.// Size of unsigned char 8 bits.// Sequential processing model.//// See copyright notice further below.//// For application runs, include the package as header file// and invoke in the main program://// (a) one call of aessetup(keylength), where keylength is // one of 128, 192 and 256.//// (b) after placing the user-given key in the byte-array // ukey.b[16], one call of aeskeyschedule(encrypt) or // aeskeyschedule(decrypt), depending on whether // encryption or decryption is to be done.//// (c) one call of aesprocess() for processing each input // block provided in the byte-array aesin.b[16] to result // in the output block in the byte-array aesout.b[16].//// Redo (a), if a different keylength is to be used. Redo // (b), if one changes key or switches from encryption to // decryption (or vice versa).//// For a demonstration with the example vectors of FIPS-197,// Appendix C, and benchmarking of the individual functions// mentioned in (a), (b) and (c) above, include the package // as header file and invoke in a main program the function// call aesdemo(). Check carefully with FIPS-197 that the // results (ciphertexts and recovered plaintexts) are indeed // correct before any practical applications of the package.//// The Supplement is informative only and is intended for // rendering easier the understanding or checking of certain // functions and for benchmark comparisons with other AES // implementations.//// Release 1.4, as originally issued, is available at // http://home.t-online.de/home/mok-kong.shen.//------------------------------------------------------------- */#include <stdio.h> #include <stdlib.h> #include <time.h>#include "MKS_AES.h"/* moved to headertypedef unsigned char byte;typedef unsigned int word;*/typedef union { byte b[4]; word w;} UU;/* moved to headertypedef union { byte b[16]; byte bm[4][4]; word w[4];} BLOCK;*//* ----------------------------------------------------------// aesin and aesout are input/output of the function aesprocess.// These are to be considered by the user as byte-arrays, not as// arrays of unsigned int. Beware of confusion and potential// errors due to the endian-ness of hardware, resulting in// non-interoperability, when implementing CTR mode with integer// arithmetic operations without due consideration of the// effect of endian-ness.------------------------------------------------------------- */BLOCK aesin,aesout;const int Nb=4; int Nk,Nr,Nr4minus1; int ekeywdim,ekeywdimminus1,roundpairs;int aessetupdone=0;/* ----------------------------------------------------------// ukey is the user-given key, ekey is the expanded key.// Maximum storage space is provided for ukey and ekey. Size of// ekey provides for a max. of 14 rounds. The actual size in // words is Nk for ukey and ekeywdim for ekey. See FIPS-197 and // the function aessetup. For ekey, for implementation reasons,// four additional words are provided but not actually used in // encryption/decrpyption processing, see the function // aeskeyschedule.------------------------------------------------------------- *//* moved to headertypedef union { byte b[32]; byte bm[8][4]; word w[8];} USERKEY;*/USERKEY ukey;typedef union { byte b[256]; byte bm[64][4]; word w[64];} EXPANDEDKEY;EXPANDEDKEY ekey;/* ----------------------------------------------------------// For elements of the array sbox, see FIPS-197. ------------------------------------------------------------- */byte sbox[256]={0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16 };byte invsbox[256];static byte gfmult(byte a, byte b){ byte r,t; if (a < b) { t=b; b=a; a=t; } r=0; do { if (b&0x01) r^=a; if (a&0x80) a=(a<<1)^0x1b; else a<<=1; } while (b>>=1); return r;}typedef union { byte b[1024]; byte bm[256][4]; word w[256];} TABLE;/* ----------------------------------------------------------// The tables t's and v's are for encryption and decryption // respectively. (See the book of Daemen and Rijmen, pp.56-59,// for detailed explanation of the tables t's.)// The tables z's are similar to the v's but without the // involvement of substitution. The tables u's and w's are // similar to the tables t's and v's but use an identity // matrix. The table y is the identity of the byte extended // with three zero bytes. // We have introduced the additional tables u's, w's, y and // z's for enabling more efficient processing in the functions// asekeyschedule and aesprocess.------------------------------------------------------------- */TABLE t0,t1,t2,t3,u0,u1,u2,u3,v0,v1,v2,v3,w0,w1,w2,w3,y, z0,z1,z2,z3;static void computetables(){ int i,j; byte s,r; for (i=0; i<256; i++) invsbox[sbox[i]]=i; for (i=0; i<256; i++) { s=sbox[i]; t0.bm[i][0]=gfmult(s,0x02); t0.bm[i][1]=t0.bm[i][2]=s; t0.bm[i][3]=gfmult(s,0x03); u0.bm[i][0]=s; u0.bm[i][1]=u0.bm[i][2]=u0.bm[i][3]=0; y.bm[i][0]=i; y.bm[i][1]=y.bm[i][2]=y.bm[i][3]=0; r=invsbox[i]; v0.bm[i][0]=gfmult(r,0x0e); v0.bm[i][1]=gfmult(r,0x09); v0.bm[i][2]=gfmult(r,0x0d); v0.bm[i][3]=gfmult(r,0x0b); z0.bm[i][0]=gfmult(i,0x0e); z0.bm[i][1]=gfmult(i,0x09); z0.bm[i][2]=gfmult(i,0x0d); z0.bm[i][3]=gfmult(i,0x0b); w0.bm[i][0]=r; w0.bm[i][1]=w0.bm[i][2]=w0.bm[i][3]=0; for (j=0; j<4; j++) { t1.bm[i][j]=t0.bm[i][(j+3)%4]; t2.bm[i][j]=t0.bm[i][(j+2)%4]; t3.bm[i][j]=t0.bm[i][(j+1)%4]; u1.bm[i][j]=u0.bm[i][(j+3)%4]; u2.bm[i][j]=u0.bm[i][(j+2)%4]; u3.bm[i][j]=u0.bm[i][(j+1)%4]; v1.bm[i][j]=v0.bm[i][(j+3)%4]; v2.bm[i][j]=v0.bm[i][(j+2)%4]; v3.bm[i][j]=v0.bm[i][(j+1)%4]; w1.bm[i][j]=w0.bm[i][(j+3)%4]; w2.bm[i][j]=w0.bm[i][(j+2)%4]; w3.bm[i][j]=w0.bm[i][(j+1)%4]; z1.bm[i][j]=z0.bm[i][(j+3)%4]; z2.bm[i][j]=z0.bm[i][(j+2)%4]; z3.bm[i][j]=z0.bm[i][(j+1)%4]; } }}void aessetup(int keylength){ if (!aessetupdone) { computetables(); aessetupdone=1; } switch(keylength) { case 128: Nk=4; Nr=10; break; case 192: Nk=6; Nr=12; break; case 256: Nk=8; Nr=14; break; default: printf("\nwrong keylength in aessetup call\n"); exit(1); } Nr4minus1=Nr*4-1; ekeywdim=Nb*(Nr+1); ekeywdimminus1=ekeywdim-1; roundpairs=Nr/2;}const byte RC[12]={ 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c };/* moved to headertypedef enum { encrypt, decrypt } PROCESS;*/PROCESS encdec;/* ----------------------------------------------------------// The function aeskeyschedule utilizes the tables u's and// the table y, the table z's and partial loop-unrolling to // do the same as the function aeskeyschedule_version1 in the // Supplement but more efficiently. See FIPS-197 and the function // computetables. For elements of the array RC (size provided for // max. of 14 rounds), see the book of Daemen and Rijmen, p.214. // Before calling aeskeyschedule, key of the user must be// available in the array ukey.b in the bytes from ukey.b[0] // to ukey.b[4*Nk-1].// It is assumed that aessetup has been called previously// with the correct keylength.------------------------------------------------------------- */void aeskeyschedule(PROCESS kind) { int i,ii; word *wp; byte *bp; if (!aessetupdone) { printf( "\nerror: aessetup was not called. program aborted\n"); exit(1); } encdec=kind; for (i=0; i < Nk; i++) ekey.w[i]=ukey.w[i]; ii=0; wp=&ekey.w[Nk]; bp=(byte *) &ekey.w[Nk-1]; if (Nk==4) for (i=0; i < 10; i++) { wp[0]=wp[-4]^y.w[RC[++ii]]^ u0.w[bp[1]]^u1.w[bp[2]]^u2.w[bp[3]]^u3.w[bp[0]]; wp[1]=wp[-3]^wp[0]; wp[2]=wp[-2]^wp[1]; wp[3]=wp[-1]^wp[2]; wp+=4; bp+=16; } else if (Nk==6) for (i=0; i < 8; i++) { wp[0]=wp[-6]^y.w[RC[++ii]]^ u0.w[bp[1]]^u1.w[bp[2]]^u2.w[bp[3]]^u3.w[bp[0]]; wp[1]=wp[-5]^wp[0]; wp[2]=wp[-4]^wp[1]; wp[3]=wp[-3]^wp[2]; wp[4]=wp[-2]^wp[3]; wp[5]=wp[-1]^wp[4]; wp+=6; bp+=24; } else for (i=0; i < 7; i++) { wp[0]=wp[-8]^y.w[RC[++ii]]^ u0.w[bp[1]]^u1.w[bp[2]]^u2.w[bp[3]]^u3.w[bp[0]]; wp[1]=wp[-7]^wp[0]; wp[2]=wp[-6]^wp[1]; wp[3]=wp[-5]^wp[2]; bp+=16; wp[4]=wp[-4]^ u0.w[bp[0]]^u1.w[bp[1]]^u2.w[bp[2]]^u3.w[bp[3]]; wp[5]=wp[-3]^wp[4]; wp[6]=wp[-2]^wp[5]; wp[7]=wp[-1]^wp[6]; wp+=8; bp+=16; } if (encdec==decrypt) {/* ----------------------------------------------------------// The first and the last round key are excluded from the// inverse mixcolumns transform. See the book of Daemen and // Rijmen, p.59.------------------------------------------------------------- */ bp=(byte *) &ekey.w[4]; for (ii=4; ii<=Nr4minus1; ii++) { ekey.w[ii]=z0.w[bp[0]]^z1.w[bp[1]]^ z2.w[bp[2]]^z3.w[bp[3]]; bp+=4; } }}/* ----------------------------------------------------------// Before calling aesprocess, input data must be available // in the array aesin.b (bytes aesin.b[0] to aesin.b[15]). // Output will be in the array aesout.b (bytes aesout.b[0] // to aesout.b[15]). It is assumed (not checked) that // aeskeyschedule has been called previously. The function // aesprocess employs partial loop-unrolling and two // alternating buffers temp0 and temp1 and also the tables u's // and w's to do the same as the function aesprocess_version1 // in the Supplement but more efficiently. The loops operate on // pairs of rounds. Note that, for implementation reasons, the // matrices involved are the transposes of the corresponding // ones in FIPS-197, hence the difference in indexing of their // elements. Note also that in AES Nr is always even and that // the final round is different, hence the last two rounds // are separated from the loop. For decryption, see the book// of Daemen and Rijmen, p.48-50.------------------------------------------------------------- */BLOCK temp0,temp1;void aesprocess() { int grdp; word *wp; if (encdec==encrypt) { wp=&ekey.w[0]; temp0.w[0]=(*wp++)^aesin.w[0]; temp0.w[1]=(*wp++)^aesin.w[1]; temp0.w[2]=(*wp++)^aesin.w[2]; temp0.w[3]=(*wp++)^aesin.w[3]; for (grdp=1; grdp < roundpairs; grdp++) { temp1.w[0]=(*wp++)^ t0.w[temp0.bm[0][0]]^t1.w[temp0.bm[1][1]]^ t2.w[temp0.bm[2][2]]^t3.w[temp0.bm[3][3]]; temp1.w[1]=(*wp++)^ t0.w[temp0.bm[1][0]]^t1.w[temp0.bm[2][1]]^ t2.w[temp0.bm[3][2]]^t3.w[temp0.bm[0][3]];
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -