bst128 ProcessAD(u64 adlen,const unsigned char *ad, u32* rkey_enc,bst128 kappa,bst128 preIC){ /*variable declarations */ u64 j,blockadlen; u64* adv=(u64*)ad; bst128 sin,sout; bst128 partial; bst128 counter; u64 kount=0; bst128 initcounter=SETUPcounterLEFT(preIC); bst128 checksum; /*end variable declaration */ checksum.s[0]=0;checksum.s[1]=0; if(adlen>0){ counter=NADD64(kappa,initcounter); blockadlen=(adlen/16);/*number of ad full blocks*/ j=0; while(j<blockadlen){ sin.s[0]=adv[2*j]; sin.s[1]=adv[2*j+1]; sout=TAES_ENCRYPT(sin,rkey_enc,counter); XOR128(checksum,sout); counter=NADD64(counter,initcounter); j++; }/*endwhile. Now only a possible partial block exists */ j=(j<<4); if(j<adlen){ /*we DO have a partial block*/ partial.s[0]=partial.s[1]=0; while(j+kount<adlen){ partial.b[kount]=ad[j+kount]; kount++; }/*endwhile */ partial.b[kount]=1; sout=TAES_ENCRYPT(partial,rkey_enc,kappa); /*kappa is never used elsewhere*/ XOR128(checksum,sout); }/* end if j<adlen. no need to update counter*/ }/*end if adlen*/ return checksum; }
static void EF(uint32_t *d, const uint32_t *rk) { uint32_t t[4]; //XOR D with RK XOR128(d, rk); //Substitution layer SL2 SL2(t, d); //Diffusion layer A(d, t); }
//the finalization state of AEGIS void aegis128_tag_generation(unsigned long long msglen, unsigned long long adlen, unsigned char maclen, unsigned char *mac, unsigned char *state) { int i; unsigned char tmp[16]; unsigned char msgtmp[16]; ((unsigned long long*)msgtmp)[0] = adlen << 3; ((unsigned long long*)msgtmp)[1] = msglen << 3; XOR128(msgtmp, msgtmp, state+48); for (i = 0; i < 7; i++) { //state update function memcpy(tmp, state+64, 16); AESROUND(state+64, state+48, state+64); AESROUND(state+48, state+32, state+48); AESROUND(state+32, state+16, state+32); AESROUND(state+16, state+0, state+16); AESROUND(state+0, tmp, state+0); //xor "msg" with state[0] XOR128(state, state, msgtmp); } XOR128(state+64, state+64, state+48); XOR128(state+64, state+64, state+32); XOR128(state+64, state+64, state+16); XOR128(state+64, state+64, state+0); //in this program, the mac length is assumed to be multiple of bytes memcpy(mac, state+64, maclen); }
/*The input to initialization is the 128-bit key; 128-bit IV;*/ void aegis128_initialization(const unsigned char *key, const unsigned char *iv, unsigned char *state) { int i; unsigned char constant[32] = {0x0,0x1,0x01,0x02,0x03,0x05,0x08,0x0d,0x15,0x22,0x37,0x59,0x90,0xe9,0x79,0x62,0xdb,0x3d,0x18,0x55,0x6d,0xc2,0x2f,0xf1,0x20,0x11,0x31,0x42,0x73,0xb5,0x28,0xdd}; unsigned char tmp[16]; unsigned char keytmp[16]; unsigned char ivtmp[16]; memcpy(keytmp, key, 16); memcpy(ivtmp, iv, 16); memcpy(state, ivtmp, 16); memcpy(state+16, constant+16, 16); memcpy(state+32, constant+0, 16); XOR128(state+48, keytmp, constant); XOR128(state+64, keytmp, constant + 16); XOR128(state, state, keytmp); XOR128(keytmp, keytmp, ivtmp); for (i = 0; i < 10; i++) { //state update function memcpy(tmp, state+64, 16); AESROUND(state+64, state+48, state+64); AESROUND(state+48, state+32, state+48); AESROUND(state+32, state+16, state+32); AESROUND(state+16, state+0, state+16); AESROUND(state+0, tmp, state+0); //xor msg with state[0] XOR128(keytmp, keytmp, ivtmp); XOR128(state, state, keytmp); } }
//one step of decryption inline void aegis128_dec_aut_step(unsigned char *plaintextblk, const unsigned char *ciphertextblk, unsigned char *state) { unsigned char tmp[16]; AND128(plaintextblk, state+32, state+48); XOR128(plaintextblk, plaintextblk, state+16); XOR128(plaintextblk, plaintextblk, state+64); XOR128(plaintextblk, plaintextblk, ciphertextblk); //state update function memcpy(tmp, state+64, 16); AESROUND(state+64, state+48, state+64); AESROUND(state+48, state+32, state+48); AESROUND(state+32, state+16, state+32); AESROUND(state+16, state+0, state+16); AESROUND(state+0, tmp, state+0); //message is used to update the state. XOR128(state, state, plaintextblk); }
void ariaDecryptBlock(AriaContext *context, const uint8_t *input, uint8_t *output) { uint32_t *dk; uint32_t p[4]; uint32_t q[4]; //Copy the ciphertext to the buffer memcpy(p, input, ARIA_BLOCK_SIZE); //Point to the decryption round keys dk = context->dk; //Apply 11 rounds OF(p, dk + 0); EF(p, dk + 4); OF(p, dk + 8); EF(p, dk + 12); OF(p, dk + 16); EF(p, dk + 20); OF(p, dk + 24); EF(p, dk + 28); OF(p, dk + 32); EF(p, dk + 36); OF(p, dk + 40); //128-bit master keys require a total of 12 rounds if(context->nr == 12) { XOR128(p, dk + 44); SL2(q, p); XOR128(q, dk + 48); } //192-bit master keys require a total of 14 rounds else if(context->nr == 14) { EF(p, dk + 44); OF(p, dk + 48); XOR128(p, dk + 52); SL2(q, p); XOR128(q, dk + 56); } //256-bit master keys require a total of 16 rounds else { EF(p, dk + 44); OF(p, dk + 48); EF(p, dk + 52); OF(p, dk + 56); XOR128(p, dk + 60); SL2(q, p); XOR128(q, dk + 64); } //The resulting value is the plaintext memcpy(output, q, ARIA_BLOCK_SIZE); }
int crypto_aead_decrypt( unsigned char *m,unsigned long long *mlen, unsigned char *nsec, const unsigned char *c,unsigned long long clen, const unsigned char *ad,unsigned long long adlen, const unsigned char *npub, const unsigned char *k){ /* declaration of variables */ bst128 checksum; bst128 kappa; u32 rkey_enc[56]; u32 rkey_dec[56];/* decryption round keys*/ bst128 sin,sout; u64 i,j; u64* mv=(u64*)m; u64* cv=(u64*)c; u64* kv=(u64*)k; u64* npubv=(u64*)npub; bst128 wout; bst128 initcounter; bst128 counter; u64 kount=clen-TAGLENGTH; u64 blockclen=(kount/16);/*number of ciphertext full blocks,excluding tag*/ (void) nsec; /*avoid warning*/ if(clen<TAGLENGTH) return -1; initcounter.s[0]=npubv[0]; initcounter.s[1]=npubv[1];/*initially holds pub msg number*/ sin.s[0]=kv[0]; sin.s[1]=kv[1];/*get user key*/ rijndaelKeySetupEnc(rkey_enc,sin.b);/*expand user key */ /*=========get kappa====== */ rijndaelEncrypt(rkey_enc,initcounter.b,kappa.b); /*=============get session rkeys and mask=====*/ initcounter=Obtain_sessionrkeys(kappa,rkey_enc); /*=============================== associated data =================================*/ checksum=ProcessAD(adlen,ad,rkey_enc,kappa,initcounter); /*========================================================== DECRYPT CIPHERTEXT =======================================================*/ counter=NADD64(kappa,initcounter); *mlen=clen-TAGLENGTH; j=0; if(clen>TAGLENGTH){ /*obtain decryption keys*/ CONVERT2DECKEY(rkey_enc,rkey_dec); while(j<blockclen){ sin.s[0]=cv[2*j];sin.s[1]=cv[2*j+1]; XORADD(checksum.s,sin,counter); sout=TAES_DECRYPT(sin,rkey_dec,counter); XOR128(checksum,sout); mv[2*j]=sout.s[0];mv[2*j+1]=sout.s[1]; counter=NADD64(counter,initcounter); j++; }/*endwhile. */ j=(j<<4); if(j<kount){ /*last block is partial, then */ sout=PartialBlock(kount,rkey_enc,j,c,m,0,initcounter,counter); XOR128(checksum,sout); }/*endif j */ }/*end decryption ========================== VERIFY TAG ===========================*/ wout=TAG(checksum,adlen,kount,rkey_enc,kappa); j=0; /*to avoid side attacks and to try to fool the compiler into not optimizing too much*/ for(i=0;i<TAGLENGTH;i++) { if(wout.b[i]!=c[kount+i]) j+=2; else j++; } if(j>TAGLENGTH) return -1; return 0; }/* ===============END aead decrypt ========================*/
int crypto_aead_encrypt(unsigned char *c, unsigned long long *clen, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k){ bst128 checksum; bst128 kappa; u32 rkey_enc[56]; bst128 sin,sout;/*for single block enc and to process key*/ u64 i,j; u64 blockmlen=(mlen/16); /*number of plain full blocks*/ u64* mv=(u64*)m; u64* cv=(u64*)c; u64* kv=(u64*)k; u64* npubv=(u64*)npub; bst128 wout; bst128 initcounter; bst128 counter; (void) nsec; /*avoid warning*/ initcounter.s[0]=npubv[0]; initcounter.s[1]=npubv[1];/*initially holds nonce,later IC*/ sin.s[0]=kv[0]; sin.s[1]=kv[1];/*get user key*/ rijndaelKeySetupEnc(rkey_enc,sin.b);/*expand user key */ /*=========get kappa====== */ rijndaelEncrypt(rkey_enc,initcounter.b,kappa.b); /*=============get session rkeys and mask=====*/ initcounter=Obtain_sessionrkeys(kappa,rkey_enc); /*=============================== associated data =================================*/ checksum=ProcessAD(adlen,ad,rkey_enc,kappa,initcounter); /*=========================================== ENCRYPT PLAINTEXT ============================================== */ counter=NADD64(kappa,initcounter); *clen=mlen+TAGLENGTH; j=0; if(mlen>0){ while(j<blockmlen){ sin.s[0]=mv[2*j]; sin.s[1]=mv[2*j+1]; XOR128(checksum,sin); sout=TAES_ENCRYPT(sin,rkey_enc,counter); cv[2*j]=sout.s[0]; cv[2*j+1]=sout.s[1]; XORADD(checksum.s,sout,counter); counter=NADD64(counter,initcounter); j++; }/*endwhile. Now only a possible partial block exists */ j=(j<<4); if(j<mlen){ /*last block is partial, then */ sout=PartialBlock(mlen,rkey_enc,j,m,c,1,initcounter,counter); XOR128(checksum,sout); }/*endif j<mlen */ }/*endif mlen>0, end encryption */ /*========================= TAG ===========================*/ wout=TAG(checksum,adlen,mlen,rkey_enc,kappa); for(i=0;i<TAGLENGTH;i++) c[mlen+i]=wout.b[i]; return 0; }/*end AEAD encrypt*/
error_t ariaInit(AriaContext *context, const uint8_t *key, size_t keyLength) { uint_t i; uint32_t *ek; uint32_t *dk; const uint32_t *ck1; const uint32_t *ck2; const uint32_t *ck3; uint32_t w[16]; //128-bit master key? if(keyLength == 16) { //Select the relevant constants ck1 = c + 0; ck2 = c + 4; ck3 = c + 8; //The number of rounds depends on the size of the master key context->nr = 12; } //192-bit master key? else if(keyLength == 24) { //Select the relevant constants ck1 = c + 4; ck2 = c + 8; ck3 = c + 0; //The number of rounds depends on the size of the master key context->nr = 14; } //256-bit master key? else if(keyLength == 32) { //Select the relevant constants ck1 = c + 8; ck2 = c + 0; ck3 = c + 4; //The number of rounds depends on the size of the master key context->nr = 16; } else { //Report an error return ERROR_INVALID_KEY_LENGTH; } //Compute 128-bit values KL and KR memset(w, 0, sizeof(w)); memcpy(w, key, keyLength); //Save KR... MOV128(w + 8, w + 4); //Compute intermediate values W0, W1, W2, and W3 MOV128(w + 4, w + 0); OF(w + 4, ck1); XOR128(w + 4, w + 8); MOV128(w + 8, w + 4); EF(w + 8, ck2); XOR128(w + 8, w + 0); MOV128(w + 12, w + 8); OF(w + 12, ck3); XOR128(w + 12, w + 4); //Convert from big-endian byte order to host byte order for(i = 0; i < 16; i++) w[i] = betoh32(w[i]); //Point to the encryption round keys ek = context->ek; //Compute ek1, ..., ek17 as follow ROL128(ek + 0, w + 4, 109); XOR128(ek + 0, w + 0); ROL128(ek + 4, w + 8, 109); XOR128(ek + 4, w + 4); ROL128(ek + 8, w + 12, 109); XOR128(ek + 8, w + 8); ROL128(ek + 12, w + 0, 109); XOR128(ek + 12, w + 12); ROL128(ek + 16, w + 4, 97); XOR128(ek + 16, w + 0); ROL128(ek + 20, w + 8, 97); XOR128(ek + 20, w + 4); ROL128(ek + 24, w + 12, 97); XOR128(ek + 24, w + 8); ROL128(ek + 28, w + 0, 97); XOR128(ek + 28, w + 12); ROL128(ek + 32, w + 4, 61); XOR128(ek + 32, w + 0); ROL128(ek + 36, w + 8, 61); XOR128(ek + 36, w + 4); ROL128(ek + 40, w + 12, 61); XOR128(ek + 40, w + 8); ROL128(ek + 44, w + 0, 61); XOR128(ek + 44, w + 12); ROL128(ek + 48, w + 4, 31); XOR128(ek + 48, w + 0); ROL128(ek + 52, w + 8, 31); XOR128(ek + 52, w + 4); ROL128(ek + 56, w + 12, 31); XOR128(ek + 56, w + 8); ROL128(ek + 60, w + 0, 31); XOR128(ek + 60, w + 12); ROL128(ek + 64, w + 4, 19); XOR128(ek + 64, w + 0); //Convert from host byte order to big-endian byte order for(i = 0; i < 68; i++) ek[i] = htobe32(ek[i]); //Decryption round keys are derived from the encryption round keys dk = context->dk; //Compute dk1 MOV128(dk + 0, ek + context->nr * 4); //Compute dk2, ..., dk(n) for(i = 1; i < context->nr; i++) A(dk + i * 4, ek + (context->nr - i) * 4); //Compute dk(n + 1) MOV128(dk + i * 4, ek + 0); //No error to report return NO_ERROR; }