Paul Kim
Paul Kim

Reputation: 146

Rijndael S-box in C

I am trying to write a function which computes the Rijndael S-box according to this Wikipedia article. Rijndael S-box

#define ROTL8(x,shift) ((uint8_t) ((x) << shift | ((x) >> (8 - (shift)))))
uint8_t sbox(uint8_t b)
{
    uint8_t s = b ^ ROTL8(b,1) ^ ROTL8(b,2) ^ ROTL8(b,3) ^ ROTL8(b,4) ^ 0x63;
    return s;
}

Now this works when I try sbox(0x00)=0x63 and sbox(0x01)=0x7c, but it starts to go astray from sbox(0x02), which should be 0x77, but I get 0x5d instead. I suspected the issue might be the rotation not working correctly, but that now does not seem like an issue...

What is wrong here?

Upvotes: 0

Views: 1383

Answers (1)

Daniel Kleinstein
Daniel Kleinstein

Reputation: 5512

This is the wrong way to implement AES's S-box - most implementations are either hardcoded (they explicitly write the entire S-box as a 256-byte array), or they iteratively build the entries of the S-box, as in the Wikipedia article you linked:

void initialize_aes_sbox(uint8_t sbox[256]) {
    uint8_t p = 1, q = 1;
    
    /* loop invariant: p * q == 1 in the Galois field */
    do {
        /* multiply p by 3 */
        p = p ^ (p << 1) ^ (p & 0x80 ? 0x1B : 0);

        /* divide q by 3 (equals multiplication by 0xf6) */
        q ^= q << 1;
        q ^= q << 2;
        q ^= q << 4;
        q ^= q & 0x80 ? 0x09 : 0;

        /* compute the affine transformation */
        uint8_t xformed = q ^ ROTL8(q, 1) ^ ROTL8(q, 2) ^ ROTL8(q, 3) ^ ROTL8(q, 4);

        sbox[p] = xformed ^ 0x63;
    } while (p != 1);

    /* 0 is a special case since it has no inverse */
    sbox[0] = 0x63;
}

notice that xformed's value - which is the value you calculated in your own implementation - changes iteratively over the iterations (and it is not the S-box value of its q the way you implemented). In practice, every manual S-box construction has some sort of similar iterative process - look over at Code Golf for some creative implementations.

Upvotes: 2

Related Questions