0

Code:

#include<stdio.h>
#include<stdlib.h>

unsigned char 
s(const unsigned char x) {
    static const unsigned char aes_s_box[16][16] = {
        {0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76},
        {0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0},
        {0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15},
        {0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75},
        {0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84},
        {0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF},
        {0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8},
        {0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2},
        {0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73},
        {0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB},
        {0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79},
        {0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08},
        {0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A},
        {0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E},
        {0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF},
        {0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}
    };
    const unsigned int row = x & 0xF0;
    const unsigned int col = x & 0x0F;
    return aes_s_box[row][col];
}

void
main(void) {
    unsigned count = 0;
    for(unsigned char i = 0x0; i <= 0xFF; i++) {
        for(unsigned char j = 0x0; j <= 0xFF; j++) {
            const unsigned char s1 = s(i);
            const unsigned char s2 = s(j);
            const unsigned char xor = i ^ j; // only for debugging
            const unsigned char s3 = s(i ^ j);
            const unsigned char lhs_check = s1 ^ s2; // only for debugging
            if(s1 ^ s2 == s3) {
                printf("x1 = %x, x2 = %x\n", i, j);
                count++;
            }
        }
    }
    printf("count = %u\n", count);
}

The code is simply supposed to check all occurrences in an aes s-box where property of linearity is satisfied.

For those unfamiliar with the concept of S-box and linearity, s-boxes are used in AES (advanced encryption standard) to achieve confusion. They are inherently non-linear, meaning, sbox(hex1) \xor sbox(x2) != sbox(x1 \xor x2). This program checks this property, meaning, nothing should ideally be printed on the screen (except for the obvious diagonal case). However, the program returns true even for lhs = 31 and rhs = 124. I wanted to know if there's something inherently wrong with using the == operator when working with hexadecimal values.

12
  • 6
    (s1 ^ s2) == s3 Bitwise operations are lower precedence than ==. Turn up the warnings in your compiler and pay attention to them. Those for loops will never end. godbolt.org/z/hWKPhndh5 Commented Mar 16, 2024 at 23:56
  • 1
    const unsigned int row = x & 0xF0; should be const unsigned int row = x >> 4; Commented Mar 16, 2024 at 23:56
  • 1
    "I wanted to know if there's something inherently wrong with using the == operator when working with hexadecimal values" - No. What makes you think there may be? i <= 0xFF and j <= 0xFF will always be true (on all common machines) though so the loops are infinite. Commented Mar 16, 2024 at 23:56
  • 2
    There are no "hex values". They are just integers. Commented Mar 17, 2024 at 0:01
  • 2
    They will run forever if the loop counter is an unsigned char with a range of 0-255. i can never contain a value that doesn't meet the loop condition. 255 is incremented and becomes 0 and the circle continues. Commented Mar 17, 2024 at 0:35

1 Answer 1

1

There is nothing inherently wrong with comparing hex values with ==.
Moreover hex values are actually just integers.

But there are 2 issues in your code:

  1. Operator precedence in your if statement:
    == has higher precedence than ^,
    and therefore this expression: s1 ^ s2 == s3
    Is actually interpreted as: s1 ^ (s2 == s3) which is not what you want.

    To fix it you should use:

    if ((s1 ^ s2) == s3) { /*...*/ }
    
  2. Both your for loops are infinite loops:
    unsigned char i and unsigned char j will always be in the range [0x0 .. 0xFF] because an unsigned char will wrap back to 0x0 (0) after a 0xFF (255) value will be incremented.

    To fix it:
    (1) Use a larger integer, e.g. unsigned int for i and j.
    (2) When calling s with expressions based on i, j cast them to unsigned char (to avoid a "possible loss of data" or similar warning).

Demo - Godbolt (output truncated)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.