/*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);


}
예제 #4
0
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;

}