/*SHELL-AES encryption for plaintexts with a length longer than one block but not a multiple of block length: parameters follow those of function shellaesEnc */ void shellaesEnc_nfb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 p[], unsigned long long int ptlen, u8 c[], u8 tag[]){ u8 V[16], U[16], checksum[16], F[16], keyprime[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; unsigned long long int pt_fblen; unsigned int pt_nfblen; pt_nfblen=ptlen%16; pt_fblen=ptlen-pt_nfblen; S= (u8 *) malloc(ptlen); I= (u8 *) malloc(ptlen); Z= (u8 *) malloc(pt_fblen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], rk[44], rkprime[44]; /*key setup*/ aesKeySetupEnc(rk, key); KeySetupEnc(mk, sk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); /*process the plaintext except the last non-full block*/ PXMAC(mk, sk, L, V, rk, ad, adlen); CENC(rkprime, S, F, nonce, ptlen); memcpy(I, p, ptlen); xor_byte_string(S, I, ptlen); checksum_state_string(I, checksum, pt_fblen); PXENC(mk, sk, L, V, Z, rk, I, pt_fblen); memcpy(U, V, 16); XEXLayerEnc(rk, Lprime, Z, c, pt_fblen); tagGen(rk, checksum, Lprime, U, F, tag, pt_fblen); /*XLS: process the last non-full block*/ XLS(rk, Lprime, p+pt_fblen, pt_fblen, pt_nfblen, c+pt_fblen, tag); /* printf("ciphertext is: \n"); printf_byte_string(c, ptlen); printf("tag value is: \n"); printf_byte_string(tag, 16); */ free(I); free(Z); free(S); }
/*SHELL-AES encryption for plaintexts of mutiple blocks long: parameters follow those of function shellaesEnc */ void shellaesEnc_fb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 p[], unsigned long long int ptlen, u8 c[], u8 tag[]){ u8 V[16], U[16], checksum[16], F[16], keyprime[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; S= (u8 *) malloc(ptlen); I= (u8 *) malloc(ptlen); Z= (u8 *) malloc(ptlen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], rk[44], rkprime[44]; /* key setup */ aesKeySetupEnc(rk, key); KeySetupEnc(mk, sk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); /*PXMAC: process associated data, and save output to V[]*/ PXMAC(mk, sk, L, V, rk, ad, adlen); /*CENC: process nonce, and save output to S[] and F[]*/ CENC(rkprime, S, F, nonce, ptlen); /*mask plaintext by xoring the output S[] of CENC, and save it to I[]*/ memcpy(I, S, ptlen); xor_byte_string(p, I, ptlen); /*PXENC: save outputs to Z[] and U[] */ PXENC(mk, sk, L, V, Z, rk, I, ptlen); memcpy(U, V, 16); /*XEX: produce the ciphertext*/ XEXLayerEnc(rk, Lprime, Z, c, ptlen); /*generate tag*/ checksum_state_string(I, checksum, ptlen); tagGen(rk, checksum, Lprime, U, F, tag, ptlen); /* printf("ciphertext is: \n"); printf_byte_string(c, ptlen); printf("tag value is: \n"); printf_byte_string(tag, 16); */ free(I); free(Z); free(S); }
/*SHELL-AES decryption for plaintexts with a length longer than one block but not a multiple of block length: shellaesDec_fb is used to decrypt of the ciphertext without the last non-full block; parameters follow those of function shellaesEnc */ void shellaesDec_fb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 c[], unsigned long long int ctlen, u8 p[], u8 tag[]){ u8 V[16], U[16], checksum[16], keyprime[16], F[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; S=(u8 *) malloc(ctlen); I=(u8 *) malloc(ctlen); Z=(u8 *) malloc(ctlen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], isk[12*d], rk[44], irk[44], rkprime[44]; aesKeySetupEnc(rk, key); aesKeySetupDec(irk, key); KeySetupDec(mk, sk, isk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); PXMAC(mk, sk, L, V, rk, ad, adlen); XEXLayerDec(irk, Lprime, c, Z, ctlen); PXDEC(mk, isk, L, V, Z, rk, I, ctlen); memcpy(U, V, 16); checksum_state_string(I, checksum, ctlen); CENC(rkprime, S, F, nonce, ctlen); memcpy(p, S, ctlen); xor_byte_string(I, p, ctlen); tagGen(rk, checksum, Lprime, U, F, tag, ctlen); free(I); free(S); free(Z); }
void aesKeySetupDec(u32 rk[], const u8 key[]) { int Nr, i, j; u32 temp; Nr=10; /* expand the cipher key: */ aesKeySetupEnc(rk, key); /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* apply the inverse MixColumn transform to all round keys but the first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; rk[0] = Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[0] ) & 0xff] & 0xff]; rk[1] = Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[1] ) & 0xff] & 0xff]; rk[2] = Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[2] ) & 0xff] & 0xff]; rk[3] = Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[3] ) & 0xff] & 0xff]; } }
/* SHELL-AES decryption for plaintexts shorter than one blocks long: parameters follow those of function shellaesEnc */ int shellaesDec_short(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 c[], unsigned long long int ctlen, u8 p[], const u8 tag[]){ u8 V[16], F[16], keyprime[16], L[16], Lprime[16], S[16], I[16]; u32 mk[4*d], sk[12*d], rk[44], irk[44], rkprime[44]; u8 pt1[16], pt2[16], ct1[16], ct2[16]; u8 mask[16], mask1[16]; u8 temp[16]; int i, flag; /* key setup */ aesKeySetupEnc(rk, key); KeySetupEnc(mk, sk, L, Lprime, keyprime, rk, key); aesKeySetupDec(irk, key); aesKeySetupEnc(rkprime, keyprime); memset(V, 0, 16); /*PX-MAC*/ PXMAC(mk, sk, L, V, rk, ad, adlen); /*derive the block of ciphertext and save it to ct1[]*/ memcpy(ct1, c, ctlen); for(i=ctlen; i<16; ++i){ ct1[i]=tag[i-ctlen]; } /*produce mask 3^3*Lprime*/ memcpy(mask, Lprime, 16); for(i=0; i<3; ++i){ memcpy(temp, mask, 16); double_mask(mask); xor_byte_string(temp, mask, 16); } /*produce mask 2^2*3^3*Lprime*/ memcpy(mask1, mask, 16); double_mask(mask1); double_mask(mask1); /*decrypt to obtain I[]*/ xor_byte_string(mask1, ct1, 16); aesDecrypt(irk, ct1, pt1); xor_byte_string(mask1, pt1, 16); xor_byte_string(V, pt1, 16); memcpy(ct1, pt1, 16); xor_byte_string(ct1, V, 16); xor_byte_string(mask, ct1, 16); aesDecrypt(irk, ct1, pt1); xor_byte_string(mask, pt1, 16); memcpy(I, pt1, 16); /*decrypt the plaintext*/ CENC(rkprime, S, F, nonce, 16); xor_byte_string(S, pt1, 16); memcpy(p, pt1, ctlen); /*verify the validness of tag*/ memcpy(pt2, I, 16); double_mask(mask); xor_byte_string(mask, pt2, 16); aesEncrypt(rk, pt2, ct2); xor_byte_string(mask, ct2, 16); xor_byte_string(V, ct2, 16); memcpy(pt2, ct2, 16); double_mask(mask1); xor_byte_string(mask1, pt2, 16); aesEncrypt(rk, pt2, ct2); xor_byte_string(mask1, ct2, 16); xor_byte_string(F, ct2, 16); flag=1; if(pt1[ctlen]!=0x80){ flag=0; } for(i=ctlen+1; i<16; ++i){ if(pt1[i]!=0){ flag=0; } } for(i=0; i<ctlen; ++i){ if(ct2[i]!=tag[i+16-ctlen]){ flag=0; } } /* if(flag){ printf("the plaintext is:\n"); printf_byte_string(p, ctlen); } else{ printf("the tag is invalid!"); } */ return flag; }
/* SHELL-AES encryption for plaintexts shorter than one blocks long: parameters follow those of function shellaesEnc */ void shellaesEnc_short(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 p[], unsigned long long int ptlen, u8 c[], u8 tag[]){ u8 V[16], F[16], keyprime[16], L[16], Lprime[16], S[16], I[16]; u32 mk[4*d], sk[12*d], rk[44], rkprime[44]; u8 pt[16], pt1[16], pt2[16], ct1[16], ct2[16]; u8 mask[16]; u8 temp[16]; int i; /*key setup*/ aesKeySetupEnc(rk, key); KeySetupEnc(mk, sk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); /*PXMAC: process the associated data and save output to V[]*/ memset(V, 0, 16); PXMAC(mk, sk, L, V, rk, ad, adlen); /*CENC: process nonce and save the output to S[] and F[]*/ CENC(rkprime, S, F, nonce, 16); /*pad p[] to a full block and save it to pt[]*/ memset(pt, 0, 16); memcpy(pt, p, ptlen); pt[ptlen]=0x80; /*mask pt[] by xoring the output S[] of CENC, and save it to I[] */ memcpy(I, S, 16); xor_byte_string(pt, I, 16); /*compute 3^3*Lprime and save it to mask[]*/ memcpy(mask, Lprime, 16); for(i=0; i<3; ++i){ memcpy(temp, mask, 16); double_mask(mask); xor_byte_string(temp, mask, 16); } /*compute XEX cipher with tweak of 3^3*Lprime and input I[], and save the output to ct1[]*/ memcpy(pt1, I, 16); xor_byte_string(mask, pt1, 16); aesEncrypt(rk, pt1, ct1); xor_byte_string(mask, ct1, 16); /*compute XEX cipher with tweak of 2*3^3*Lprime and input I[], and save the output to ct2[]*/ double_mask(mask); memcpy(pt2, I, 16); xor_byte_string(mask, pt2, 16); aesEncrypt(rk, pt2, ct2); xor_byte_string(mask, ct2, 16); /*compute XEX cipher with tweak of 2^2*3^3*Lprime and input of xoring ct1 and the output V of PX-MAC, and save the output to ct1[]*/ xor_byte_string(ct1, V, 16); memcpy(pt1, V, 16); double_mask(mask); xor_byte_string(mask, pt1, 16); aesEncrypt(rk, pt1, ct1); xor_byte_string(mask, ct1, 16); /*compute XEX cipher with tweak of 2^3*3^3*Lprime and input of xoring ct2 and the updated V, and save the output to ct2[]*/ xor_byte_string(ct2, V, 16); memcpy(pt2, V, 16); double_mask(mask); xor_byte_string(mask, pt2, 16); aesEncrypt(rk, pt2, ct2); xor_byte_string(mask, ct2, 16); /*xor ct2 with the output F of CENC*/ xor_byte_string(F, ct2, 16); /*tag splitting: produce the ciphertext and tag from ct1 and ct2*/ memcpy(c, ct1, ptlen); for(i=ptlen; i<16; ++i){ tag[i-ptlen]=ct1[i]; } for(i=0; i<ptlen; ++i){ tag[16-ptlen+i]=ct2[i]; } /* printf("ciphertext is: \n"); printf_byte_string(c, ptlen); printf("tag value is: \n"); printf_byte_string(tag, 16); */ }
/*SHELL-AES decryption for plaintexts of mutiple blocks long: parameters follow those of function shellaesEnc */ int shellaesDecVef_fb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 c[], unsigned long long int ctlen, u8 p[], const u8 tag[]){ u8 V[16], U[16], checksum[16], keyprime[16], F[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; S=(u8 *) malloc(ctlen); I=(u8 *) malloc(ctlen); Z=(u8 *) malloc(ctlen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], isk[12*d], rk[44], irk[44], rkprime[44]; /*setup key materials*/ aesKeySetupEnc(rk, key); aesKeySetupDec(irk, key); KeySetupDec(mk, sk, isk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); /*process associated data*/ PXMAC(mk, sk, L, V, rk, ad, adlen); /*decryption of XEX layer*/ XEXLayerDec(irk, Lprime, c, Z, ctlen); /*decryption of PXENC layer*/ PXDEC(mk, isk, L, V, Z, rk, I, ctlen); /*CENC layer*/ CENC(rkprime, S, F, nonce, ctlen); /*produce the plaintext*/ memcpy(p, S, ctlen); xor_byte_string(I, p, ctlen); /*verify the validness of tag*/ int flag; memcpy(U, V, 16); checksum_state_string(I, checksum, ctlen); flag=tagVef(rk, checksum, Lprime, U, F, tag, ctlen); /* if(flag){ printf("the plaintext is:\n"); printf_byte_string(p, ctlen); } else{ printf("the tag is invalid!"); } */ free(I); free(S); free(Z); return flag; }
/*SHELL-AES decryption for ciphertexts with a length longer than one block but not a multiple of block length: parameters follow those of function shellaesEnc */ int shellaesDec_nfb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 c[], unsigned long long int ctlen, u8 p[], const u8 tag[]){ u8 V[16], U[16], checksum[16], F[16], keyprime[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; u8 tempTag[16], tempTag2[16]; int i, flag; unsigned long long int ct_fblen; unsigned int ct_nfblen; ct_nfblen=ctlen%16; ct_fblen=ctlen-ct_nfblen; S= (u8 *) malloc(ctlen); I= (u8 *) malloc(ctlen); Z= (u8 *) malloc(ct_fblen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], isk[12*d], rk[44], irk[44], rkprime[44]; /*setup key*/ aesKeySetupEnc(rk, key); aesKeySetupDec(irk, key); KeySetupDec(mk, sk, isk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); /*decrypt the last non-full block*/ memcpy(tempTag, tag, 16); XLSInv(irk, Lprime, c+ct_fblen, ct_fblen, ct_nfblen, p+ct_fblen, tempTag); /*process associated data*/ PXMAC(mk, sk, L, V, rk, ad, adlen); /*decryption of XEX layer*/ XEXLayerDec(irk, Lprime, c, Z, ct_fblen); /*decryption of PXENC layer*/ PXDEC(mk, isk, L, V, Z, rk, I, ct_fblen); memcpy(U, V, 16); /*process nonce*/ CENC(rkprime, S, F, nonce, ctlen); /*produce plaintext*/ memcpy(p, I, ct_fblen); xor_byte_string(S, p, ct_fblen); /*verify the validness of tag*/ checksum_state_string(I, checksum, ct_fblen); tagGen(rk, checksum, Lprime, U, F, tempTag2, ct_fblen); flag=1; for(i=0; i<16; ++i){ if(tempTag[i]!=tempTag2[i]){ flag=0; } } /* if(flag){ printf("the plaintext is: \n"); printf_byte_string(p, ctlen); } else{ printf("the tag is invalid!"); } */ return flag; }