Skip to content

AES

AES

  • Restricted to block size of 128 bits and keys sizes of 128, 192 and 256 bits.
  • AES is a substitution-permutation network.
  • AES-128 only takes 12.6 cycles per byte

AES as a commic

Why you don't make your own

  • The SBox lookup is vulnerable to timing attacks
  • The SBox lookup is vulnerable to cache attacks
    • Vulnerable to Meltdown and Spectre Vulnerabilities
  • Modern Libraries and CPUs use hardware specific instructions

    • AESENC: Perform one round of an AES encryption flow
    • AESENCLAST: Perform the last round of an AES encryption flow
    • AESDEC: Perform one round of an AES decryption flow
    • AESDECLAST: Perform the last round of an AES decryption flow
    • AESKEYGENASSIST: Assist in AES round key generation
    • AESIMC: Assist in AES Inverse Mix Columns
    • PCLMULQDQ: Carryless multiply (CLMUL)[3]

    Cache/Timing info for Sbox lookup
    In Pratice static time for Intel and Arm AES structions
    Spector (Intel Hard) rollback

Math Concepts

https://www.samiam.org/galois.html

How it works

Key Schedule

Different keys are used for each round of AES.

  1. 8 bit Circular rotation of a 32-bit word
    \[ 1d2c3a4f -> 2c3a4f1d \]
void rotate(unsigned char *in) {
        unsigned char a,c;
        a = in[0];
        for(c=0;c<3;c++) 
                in[c] = in[c + 1];
        in[3] = a;
        return;
}
  1. A rcon operation
    1 is taken to the power of 2 for in times and if there is an overflow then will

    /* Calculate the rcon used in key expansion */
    unsigned char rcon(unsigned char in) {
        unsigned char c=1;
        if(in == 0){  
        	return 0;
       	} 
        while(in != 1) {
    		unsigned char b;
    		b = c & 0x80; //Check if there will be an overflow
    		c <<= 1; //bit shift as a faster power of 2
    		if(b == 0x80) { //If there was an overflow
    			c ^= 0x1b; //bitwise or with the last byte
    		}
    	    in--; //reduce the loop counter
        }
        return c;
    }
    

    The rounds constants look like
    rcon = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]
    

  2. Substitution box Operation (Inner loop)

    1. The input is a 32-bit word and an iteration number i. The output is a 32-bit word.
    2. Copy the input over to the output
    3. Use rotate to rotate the output eight bits to the left (As done in part 1)
    4. Apply Rijndael's S-box on all four individual bytes in the output word. (As done in part 2)
    5. On just the first (leftmost, MSB) byte of the output word, exclusive or the byte with 2 to the power of i (rcon(i)).

/* This is the core key expansion, which, given a 4-byte value,
 * does some scrambling */
void schedule_core(unsigned char *in, unsigned char i) {
        char a;
        rotate(in); /* Rotate the input 8 bits to the left */
        /* Apply Rijndael's s-box on all 4 bytes */
        for(a = 0; a < 4; a++) 
                in[a] = sbox(in[a]);
        /* On just the first byte, or the round constant */
        in[0] ^= rcon(i);
}

TODO

Expanding a 128 bit key

void expand_key(unsigned char *in) {
    unsigned char t[4];
    /* c is 16 because the first sub-key is the user-supplied key */
    unsigned char c = 16;
	unsigned char i = 1;
    unsigned char a;

    /* We need 11 sets of sixteen bytes each for 128-bit mode */
    while(c < 176) {
        /* Copy the temporary variable over from the last 4-byte
         * block */
        for(a = 0; a < 4; a++) 
            t[a] = in[a + c - 4];
        /* Every four blocks (of four bytes), 
         * do a complex calculation */
        if(c % 16 == 0) {
			schedule_core(t,i);
			i++;
		}
        for(a = 0; a < 4; a++) {
            in[c] = in[c - 16] ^ t[a];
            c++;
        }
    }
}

Expanding a 192-bit key

void expand_key(unsigned char *in) {
    unsigned char t[4];
    unsigned char c = 24;
	unsigned char i = 1;
    unsigned char a;
    while(c < 208) {
        /* Copy the temporary variable over */
        for(a = 0; a < 4; a++) 
            t[a] = in[a + c - 4]; 
        /* Every six sets, do a complex calculation */
        if(c % 24 == 0) {
            schedule_code(t,i);
	    	i++;
	    }
        for(a = 0; a < 4; a++) {
            in[c] = in[c - 24] ^ t[a];
            c++;
        }
    }
}

Expanding a 256-bit key

void expand_key(unsigned char *in) {
    unsigned char t[4];
    unsigned char c = 32;
	unsigned char i = 1;
    unsigned char a;
    while(c < 240) {
        /* Copy the temporary variable over */
        for(a = 0; a < 4; a++) 
            t[a] = in[a + c - 4]; 
        /* Every eight sets, do a complex calculation */
        if(c % 32 == 0) {
            schedule_core(t,i);
			i++;
		}
        /* For 256-bit keys, we add an extra sbox to the
         * calculation */
        if(c % 32 == 16) {
            for(a = 0; a < 4; a++) 
                t[a] = sbox(t[a]);
        }
        for(a = 0; a < 4; a++) {
            in[c] = in[c - 32] ^ t[a];
            c++;
        }
    }
}

Source2

Attacks