#include #include #include"../common/util.h" #include"aes.h" extern double lap; typedef unsigned char byte; typedef obliv unsigned char obyte; //typedef obliv byte obyte; FIXME char hex(byte x) { return x<=9?x+'0':x-10+'A'; } byte fromhex(char x) { if('0'<=x&&x<='9') return x-'0'; else if('A'<=x&&x<='F') return x-'A'+10; else return x-'a'+10; } // hexIO void eprintBytes(obyte* data,unsigned len) { int i,j,p = ocCurrentParty(); for(i=0;istate+i+j*4; } void aesShiftRows(AesState* s) { int i,j; for(i=1;i<4;++i) { obyte t[4]; for(j=0;j<4;++j) t[j]=*mat(s,i,j); for(j=0;j<4;++j) *mat(s,i,j)=t[(i+j)%4]; } } void aesMixCols(AesState* s) { AesState res; int i,j,k; const byte mixer[4]={2,3,1,1}; for(i=0;i<4;++i) res.state[i]=0; for(i=0;i<4;++i) for(j=0;j<4;++j) for(k=0;k<4;++k) *mat(&res,j,i) ^= mulrj(*mat(s,k,i),mixer[(k+4-j)%4]); *s=res; } obyte rotl(obyte x) { return (x<<1)^(x>>7); } obyte aesSbox(obyte x) { obyte s=0; x=invrj(x); for(int i=0;i<5;++i) { s^=x; x=rotl(x); } return s^0x63; } void aesSubBytes(AesState* s) { for(int i=0;i<16;++i) s->state[i]=aesSbox(s->state[i]); } obliv unsigned aesKeyCore(obliv unsigned x,int iter) { obliv int rv=0; x=((x<<24)^(x>>8)); for(int i=3;i>=0;--i) rv=(rv<<8)^aesSbox((x>>i*8)&0xff); return rv^exprj(2,iter-1); } obliv unsigned packBytes(const obyte* buf) { return buf[0]^(buf[1]<<8)^(buf[2]<<16)^(buf[3]<<24); } void unpackBytes(obyte* buf,obliv unsigned r) { buf[0] = (r&0xff); buf[1] = ((r>> 8)&0xff); buf[2] = ((r>>16)&0xff); buf[3] = ((r>>24)&0xff); } // Input is in first 16 bytes of buf. Output expands it to 176 bytes void aesKeyExpand(obyte* buf) { int i=1,j,k,n=16; for(j=16;j<176;++i,j+=16) { unpackBytes(buf+j, aesKeyCore(packBytes(buf+j-4),i) ^ packBytes(buf+j-n)); for(k=4;k<16;++k) buf[j+k] = buf[j+k-4]^buf[j+k-n]; } } void aes128Cipher(obyte* block,const obyte* key) { obyte buf[176]; int i,r; AesState s; for(i=0;i<16;++i) s.state[i]=block[i]; for(i=0;i<16;++i) buf[i]=key[i]; aesKeyExpand(buf); fprintf(stderr,"Time at key expansion: %lf s\n",wallClock()-lap); for(i=0;i<16;++i) s.state[i]^=buf[i]; for(r=1;r<=10;++r) { aesSubBytes(&s); aesShiftRows(&s); if(r<10) aesMixCols(&s); for(i=0;i<16;++i) s.state[i]^=buf[i+r*16]; } for(i=0;i<16;++i) block[i]=s.state[i]; } void inverseTest() { byte res; for(int i=1;i<256;++i) { if(revealOblivChar(&res,mulrj(invrj(i),i),1) && res!=1) fprintf(stderr,"Problems with inv(%d), res=%d\n",i,res); } } void testMixCols() { byte a[][4]={{0xdb,0x13,0x53,0x45},{0xf2,0x0a,0x22,0x5c}}; byte b[][4]={{0x8e,0x4d,0xa1,0xbc},{0x9f,0xdc,0x58,0x9d}}; int i,j; bool err; AesState s; for(i=0;i<2;++i) { for(j=0;j<4;++j) *mat(&s,j,0)=a[i][j]; aesMixCols(&s); for(j=0;j<4;++j) if(revealOblivBool(&err,*mat(&s,j,0)!=b[i][j],0) && err) break; if(j<4) { fprintf(stderr,"Mixed cols failed\n"); for(j=0;j<4;++j) fprintf(stderr,"%2x",a[i][j]); fprintf(stderr," -> "); for(j=0;j<4;++j) { byte x; revealOblivBool(&x,*mat(&s,j,0),0); fprintf(stderr,"%2x",x); fprintf(stderr,"\n"); } } } } void testShiftRows() { const byte result[]={0,5,10,15, 4,9,14,3, 8,13,2,7, 12,1,6,11}; AesState s; bool err; for(int i=0;i<16;++i) s.state[i]=i; aesShiftRows(&s); for(int i=0;i<16;++i) { revealOblivBool(&err,s.state[i]!=result[i],0); if(err) break; } if(err) { fprintf(stderr,"shiftRows problem\n"); byte x[16]; for(int i=0;i<16;++i) revealOblivChar(&x[i],s.state[i],0); for(int i=0;i<16;++i) fprintf(stderr,"%2x ",x[i]); fprintf(stderr,"\n"); } } bool hexread(byte* dest,unsigned dn,const char* src,unsigned sn) { int i,j,del; char t; for(i=j=0;itestkey,32); readString(key,16,buf,1); if(ocCurrentParty()==2) hexread(buf,16,args->testplain,32); readString(block,16,buf,2); fprintf(stderr,"OT time: %lf s\n",wallClock()-lap); aes128Cipher(block,key); for(int i=0;i<16;++i) revealOblivChar(args->testcipher+i,block[i],0); fprintf(stderr,"Yao gate count: %u\n",yaoGateCount()); }