Is there an efficient way to compare these arrays? - arrays

I have a NFC scanner that obtains a tag's UID and stores it in byte TagReadB[4].
I then need to compare it to a large number of other byte arrays to see if it matches with them (i.e. if it's a recognised tag).
The recognised tags are stored like this.
uint8_t RED1[4] = {0x15, 0x4C, 0xA9, 0xFB};
uint8_t RED2[4] = {0x67, 0xFC, 0x8A, 0x16};
uint8_t RED3[4] = {0xB7, 0xC4, 0xEA, 0xA4};
uint8_t RED4[4] = {0xE7, 0x32, 0xE7, 0xA4};
uint8_t RED5[4] = {0x87, 0x33, 0xED, 0x74};
uint8_t RED6[4] = {0xB7, 0x56, 0xFA, 0xA4};
uint8_t RED7[4] = {0xB5, 0x8A, 0xB6, 0xFB};
uint8_t RED8[4] = {0x07, 0xA6, 0xF3, 0xA4};
uint8_t RED9[4] = {0xE5, 0xB2, 0x9E, 0xFB};
uint8_t RED10[4] = {0x87, 0xF8, 0x8A, 0x16};
uint8_t RED11[4] = {0x47, 0x93, 0xDA, 0xA4};
uint8_t RED12[4] = {0x87, 0x1D, 0x8A, 0x16};
uint8_t RED13[4] = {0x85, 0x83, 0xB1, 0xFB};
uint8_t RED14[4] = {0x55, 0x33, 0x9C, 0xFB};
uint8_t RED15[4] = {0x45, 0x39, 0xB7, 0xFB};
uint8_t RED16[4] = {0xA5, 0xED, 0xA5, 0xFB};
uint8_t RED17[4] = {0x85, 0x6E, 0xA1, 0xFB};
uint8_t RED18[4] = {0x17, 0xC3, 0xEF, 0xA4};
uint8_t RED19[4] = {0x37, 0xCA, 0xEB, 0xA4};
uint8_t RED20[4] = {0x15, 0x66, 0xA0, 0xFB};
uint8_t YELLOW1[4] = {0x27, 0x44, 0x73, 0xE5};
uint8_t YELLOW2[4] = {0xD7, 0x44, 0xCB, 0xE2};
uint8_t YELLOW3[4] = {0x87, 0x6E, 0x78, 0xE5};
uint8_t YELLOW4[4] = {0x27, 0x49, 0x63, 0xE5};
uint8_t YELLOW5[4] = {0xA7, 0x0D, 0x6C, 0xE5};
uint8_t YELLOW6[4] = {0x87, 0x96, 0x69, 0xE5};
uint8_t YELLOW7[4] = {0x37, 0xF9, 0xCA, 0xE2};
uint8_t YELLOW8[4] = {0xD7, 0xAE, 0xCB, 0xE2};
uint8_t YELLOW9[4] = {0xA7, 0xE3, 0x78, 0xE5};
uint8_t YELLOW10[4] = {0x47, 0x72, 0x90, 0xE5};
uint8_t BLUE1[4] = {0x73, 0xD5, 0xB7, 0xAC};
uint8_t BLUE2[4] = {0x1D, 0x5D, 0xFC, 0x69};
uint8_t BLUE3[4] = {0xBD, 0xEC, 0x8F, 0x12};
uint8_t BLUE4[4] = {0xE6, 0x9F, 0x54, 0x73};
uint8_t BLUE5[4] = {0x38, 0x74, 0x7E, 0x33};
uint8_t BLUE6[4] = {0x6D, 0x05, 0x3E, 0x12};
uint8_t BLUE7[4] = {0x9C, 0x6B, 0x4A, 0x73};
I can do the following but there must be an easier way without having to repeat 20 OR statements?
if (!memcmp(TagReadB, RED1, 4) || !memcmp(TagReadB, RED2, 4) || ...) {
//do something
}
Even better, it would be great to test on what colour of the recognised tag it matches with because there will be the same action for each colour.
e.g. if it's a red tag do x, yellow tag do y, blue tag do z.
Many thanks.

You can expand your data to
struct {uint8_t tag[4], uint8_t type}
data[] = {
{ {0x15, 0x4C, 0xA9, 0xFB}, RED},
// ...
{ {0xD7, 0xAE, 0xCB, 0xE2}, YELLOW },
// ...
};
with
#define RED 1
// etc.
(or a const byte or an enum)
Then loop this list until a match and return the resulting data[i].type
or return a 0 for "not found"

You could store the tags in multidimensional arrays:
uint8_t RED_TAGS[][4] = {
{0x15, 0x4C, 0xA9, 0xFB},
{0x67, 0xFC, 0x8A, 0x16},
...
};
uint8_t YELLOW_TAGS[][4] = {
{0x15, 0x4C, 0xA9, 0xFB},
{0x67, 0xFC, 0x8A, 0x16},
...
};
uint8_t BLUE_TAGS[][4] = {
{0x15, 0x4C, 0xA9, 0xFB},
{0x67, 0xFC, 0x8A, 0x16},
...
}
Now you can check if a tag is in one of the multidimensional arrays using a for loop:
int is_tag_in_array(uint8_t array[][4], int size, uint8_t tag[4]) {
for (int i=0;i<size;i++) {
if (memcmp(array[i], tag, 4) == 0)
return 1;
}
return 0;
}
This way you can check for the color like this:
if (is_tag_in_array(RED_TAGS, 20, TagReadB)) {
// Do something for a red tag
} else if (is_tag_in_array(YELLOW_TAGS, 10, TagReadB)) {
// Do something for a yellow tag
} else if (is_tag_in_array(BLUE_TAGS, 7, TagReadB) {
// Do something for a blue tag
} else {
// Didn't match any color
}

Related

aes 128 encryption and decryption in c without any seperate libraries and header files needed mainly in diagnostics point of view

#include <stdio.h>
#include <stdint.h>
#define Nb 4
#define Nk 4
#define Nr 10
uint8_t state[4 * Nb];
uint8_t w[Nb * (Nr + 1) * 4];
#define mul2(x) ((x << 1) ^ (((x >> 7) & 1) * 0x1b))
#define mul3(x) (mul2(x) ^ x)
#define mul9(x) (mul2(mul2(mul2(x))) ^ x)
#define mul11(x) (mul2(mul2(mul2(x)) ^ x) ^ x)
#define mul13(x) (mul2(mul2(mul2(x) ^ x)) ^ x)
#define mul14(x) (mul2(mul2(mul2(x) ^ x) ^ x))
i dont want to use lookup table for xor multiplications so used this above method as reference to caliculate the values runtime
uint8_t sbox[256] = {
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
};
uint8_t inv_sbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
uint8_t rcon[256] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d
};
uint32_t sub_bytes_word(uint32_t word) {
uint8_t* bytes = (uint8_t*)&word;
for (int i = 0; i < 4; i++) {
bytes[i] = sbox[bytes[i]];
}
return word;
}
uint32_t inv_sub_bytes_word(uint32_t word) {
uint8_t* bytes = (uint8_t*)&word;
for (int i = 0; i < 4; i++) {
bytes[i] = inv_sbox[bytes[i]];
}
return word;
}
uint32_t rot_word(uint32_t word) {
return (word << 8) | (word >> 24);
}
uint32_t sub_word(uint32_t word) {
return sub_bytes_word(word);
}
uint32_t inv_word(uint32_t word) {
return inv_sub_bytes_word(word);
}
void key_expansion(uint8_t* key) {
for (int i = 0; i < Nk; i++) {
w[i] = key[4 * i] << 24 | key[4 * i + 1] << 16 | key[4 * i + 2] << 8 | key[4 * i + 3];
}
for (int i = Nk; i < 4 * (Nr + 1); i++) {
uint32_t temp = w[i - 1];
if (i % Nk == 0) {
temp = sub_word(rot_word(temp)) ^ rcon[i / Nk - 1];
} else if (Nk > 6 && i % Nk == 4) {
temp = sub_word(temp);
}
w[i] = w[i - Nk] ^ temp;
}
for (int i = 0; i < 4 * (Nr + 1); i++) {
w[i] = inv_word(w[i]);
}
}
void sub_bytes() {
for (int i = 0; i < 4 * Nb; i++) {
state[i] = sbox[state[i]];
}
}
void shift_rows() {
uint8_t temp[4 * Nb];
for (int i = 0; i < 4 * Nb; i++) {
temp[i] = state[i];
}
for (int i = 0; i < Nb; i++) {
state[i] = temp[i];
state[i + 4] = temp[i + 4];
state[i + 8] = temp[i + 8];
state[i + 12] = temp[i + 12];
}
state[1] = temp[5];
state[5] = temp[9];
state[9] = temp[13];
state[13] = temp[1];
state[2] = temp[10];
state[6] = temp[14];
state[10] = temp[2];
state[14] = temp[6];
state[3] = temp[15];
state[7] = temp[3];
state[11] = temp[7];
state[15] = temp[11];
}
void mix_columns() {
uint8_t temp[4 * Nb];
for (int i = 0; i < 4 * Nb; i++) {
temp[i] = state[i];
}
for (int i = 0; i < Nb; i++) {
state[0 + 4 * i] = mul2(temp[0 + 4 * i]) ^ mul3(temp[1 + 4 * i]) ^ temp[2 + 4 * i] ^ temp[3 + 4 * i];
state[1 + 4 * i] = temp[0 + 4 * i] ^ mul2(temp[1 + 4 * i]) ^ mul3(temp[2 + 4 * i]) ^ temp[3 + 4 * i];
state[2 + 4 * i] = temp[0 + 4 * i] ^ temp[1 + 4 * i] ^ mul2(temp[2 + 4 * i]) ^ mul3(temp[3 + 4 * i]);
state[3 + 4 * i] = mul3(temp[0 + 4 * i]) ^ temp[1 + 4 * i] ^ temp[2 + 4 * i] ^ mul2(temp[3 + 4 * i]);
}
}
void add_round_key(int round) {
for (int i = 0; i < 4 * Nb; i++) {
state[i] ^= w[round * 4 * Nb + i];
}
}
void aes_round(int round) {
sub_bytes();
shift_rows();
mix_columns();
add_round_key(round);
}
void inv_sub_bytes() {
for (int i = 0; i < 4 * Nb; i++) {
state[i] = inv_sbox[state[i]];
}
}
void inv_shift_rows() {
uint8_t temp[4 * Nb];
for (int i = 0; i < 4 * Nb; i++) {
temp[i] = state[i];
}
for (int i = 0; i < Nb; i++) {
state[i] = temp[i];
state[i + 4] = temp[i + 4];
state[i + 8] = temp[i + 8];
state[i + 12] = temp[i + 12];
}
state[1] = temp[13];
state[5] = temp[1];
state[9] = temp[5];
state[13] = temp[9];
state[2] = temp[10];
state[6] = temp[14];
state[10] = temp[2];
state[14] = temp[6];
state[3] = temp[7];
state[7] = temp[11];
state[11] = temp[15];
state[15] = temp[3];
}
void inv_mix_columns() {
uint8_t temp[4 * Nb];
for (int i = 0; i < 4 * Nb; i++) {
temp[i] = state[i];
}
for (int i = 0; i < Nb; i++) {
state[0 + 4 * i] = mul14(temp[0 + 4 * i]) ^ mul11(temp[1 + 4 * i]) ^ mul13(temp[2 + 4 * i]) ^ mul9(temp[3 + 4 * i]);
state[1 + 4 * i] = mul9(temp[0 + 4 * i]) ^ mul14(temp[1 + 4 * i]) ^ mul11(temp[2 + 4 * i]) ^ mul13(temp[3 + 4 * i]);
state[2 + 4 * i] = mul13(temp[0 + 4 * i]) ^ mul9(temp[1 + 4 * i]) ^ mul14(temp[2 + 4 * i]) ^ mul11(temp[3 + 4 * i]);
state[3 + 4 * i] = mul11(temp[0 + 4 * i]) ^ mul13(temp[1 + 4 * i]) ^ mul9(temp[2 + 4 * i]) ^ mul14(temp[3 + 4 * i]);
}
}
void inv_aes_round(int round) {
add_round_key(round);
inv_mix_columns();
inv_shift_rows();
inv_sub_bytes();
}
Here i tried encrypt and decrypt the plain text
void encrypt(uint8_t* plaintext, uint8_t* key) {
for (int i = 0; i < 4 * Nb; i++) {
state[i] = plaintext[i];
}
key_expansion(key);
add_round_key(0);
for (int i = 1; i <= Nr; i++) {
aes_round(i);
}
}
void decrypt(uint8_t* ciphertext, uint8_t* key) {
for (int i = 0; i < 4 * Nb; i++) {
state[i] = ciphertext[i];
}
key_expansion(key);
add_round_key(Nr);
for (int i = Nr - 1; i >= 1; i--) {
inv_aes_round(i);
}
inv_aes_round(0);
}
My main function
int main() {
// Set key and plaintext
uint8_t key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
uint8_t plaintext[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
uint8_t ciphertext[16];
uint8_t decrypted[16];
// Plaintext
printf("Original plaintext: ");
for (int i = 0; i < 16; i++) {
printf("%02x ", plaintext[i]);
}
printf("\n");
// Encrypt plaintext
encrypt(plaintext, key);
printf("Ciphertext: ");
for (int i = 0; i < 4 * Nb; i++) {
printf("%02x ", state[i]);
ciphertext[i] = state[i];
}
printf("\n");
// Decrypt ciphertext
decrypt(ciphertext, key);
printf("Decrypted: ");
for (int i = 0; i < 4 * Nb; i++) {
printf("%02x ", state[i]);
decrypted[i] = state[i];
}
printf("\n");
return 0;
}
i have tried improving the code many times by assigning seperate functions to implement but every time my output is wrong .\
This is my output ; whatever i tried iam not able to get correct decrypt . iam not sure where i did mistake .
Original plaintext: 01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef
Ciphertext: ec d5 9c a4 41 cb cb e5 08 02 a3 cc 7c 39 be 74
Decrypted: 37 b8 75 c5 01 5c 74 14 b4 e9 11 d8 3c 16 cd c2

memory leak in utf8 string parser

typedef struct _utf8_multibyte {
uint8_t bytes[4]; /* always max of 4 */
int used; /* how many of the 4 bytes are used */
} utf8_multibyte_t;
typedef struct _utf8_string {
uint8_t *raw; /* raw string buffer */
uint32_t *chars; /* codepoints comprising the string */
uint64_t length; /* number of codepoints in string */
} utf8_string_t;
...
utf8_string_t *utf8_init(unsigned char *s) {
utf8_string_t *str = (utf8_string_t*)malloc(sizeof(utf8_string_t*));
if (!str) {
perror("utf8_string_t init");
return NULL;
}
str->raw = (uint8_t*)malloc(strlen(s) * sizeof(uint8_t));
if (!str->raw) {
perror("malloc raw");
return NULL;
}
memcpy(str->raw, s, strlen(s));
str->length = utf8_strlen(s);
str->chars = (uint32_t*)malloc(str->length * sizeof(uint32_t));
if (!str->chars) {
perror("malloc chars");
return NULL;
}
uint8_t *p = s;
utf8_multibyte_t mb;
mb_clear(&mb);
int j = 0;
while (*p != '\0') {
int len = utf8len(*p);
mb.used = len;
mb.bytes[0] = *p++;
for (int i = 1; i < len; ++i) mb.bytes[i] = *p++;
uint32_t cp = utf8_decode(&mb);
str->chars[j++] = cp;
printf("%x ", str->chars[j - 1]);
mb_clear(&mb);
}
return str;
}
I am testing if the initialization is going correctly with this code:
unsigned char data[] = {
0xe5, 0xbd, 0xbc, 0xe5, 0xa5, 0xb3, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0xa2, 0xe3, 0x82, 0xa4, 0xe3,
0x82, 0xb9, 0xe3, 0x82, 0x92, 0xe9, 0xa3, 0x9f, 0xe3, 0x81, 0xb9, 0xe3, 0x81, 0x9f, 0xe3, 0x81,
0x8b, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x89, 0xe8, 0xb2, 0xb7,
0xe3, 0x81, 0x84, 0xe3, 0x81, 0xab, 0xe5, 0x87, 0xba, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x91, 0xe3,
0x81, 0xbe, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0xe3, 0x80, 0x82, 0x0
};
unsigned char data1[] = {
0xe5, 0xbd, 0xbc, 0xe5, 0xa5, 0xb3, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0xa2, 0xe3, 0x82, 0xa4, 0xe3,
0x82, 0xb9, 0xe3, 0x82, 0x92, 0xe9, 0xa3, 0x9f, 0xe3, 0x81, 0xb9, 0xe3, 0x81, 0x9f, 0xe3, 0x81,
0x8b, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x89, 0xe8, 0xb2, 0xb7,
0xe3, 0x81, 0x84, 0xe3, 0x81, 0xab, 0xe5, 0x87, 0xba, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x91, 0xe3,
0x81, 0xbe, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0xe3, 0x80, 0x82, 0x0
};
utf8_string_t *str1 = utf8_init(data);
utf8_string_t *str2 = utf8_init(data1);
printf("%d %d\n", str1->length, str2->length);
/*utf8_free(str1);
utf8_free(str2);*/
One of the strings sometimes doesn't get initialized and when it does it reports it's length as 0 when it should be 25. I tried printing out the codepoints from the strings as they're initialized and they're completely ok so I am led to believe it's got something to do with the raw string allocation but I am not sure.
I know this has something to do with my memory management but I have been staring at this code for 2 days and still cannot figure out where my mistake is. Please help me.
EDIT:
I think I managed to fix it thanks to the recommendations in the comments. Here's the updated code:
utf8_string_t *utf8_init(const uint8_t *s) {
utf8_string_t *str = malloc(sizeof(utf8_string_t));
if (!str) {
free(str);
return NULL;
}
uint64_t rawlen = strlen_uchar(s);
str->raw = malloc((rawlen + 1) * sizeof(uint8_t));
if (!str->raw) {
free(str->raw);
free(str);
return NULL;
}
memcpy(str->raw, s, rawlen + 1);
str->length = utf8_strlen(s);
str->chars = malloc(str->length * sizeof(uint32_t));
if (!str->chars) {
free(str->raw);
free(str->chars);
free(str);
return NULL;
}
uint8_t *p = (uint8_t*)s;
utf8_multibyte_t mb;
mb_clear(&mb);
int j = 0;
while (*p != '\0') {
int len = utf8len(*p);
mb.used = len;
mb.bytes[0] = *p++;
for (int i = 1; i < len; ++i) mb.bytes[i] = *p++;
uint32_t cp = utf8_decode(&mb);
str->chars[j++] = cp;
mb_clear(&mb);
}
return str;
}
Please do tell if there are still parts of it which might bring about undefined behavior/bugs.

Finding polynomial used in CRC-8 calculation table

Here as most rated answer (Implementing CRC8 on Arduino to write to MLX90614) is a good example of CRC-8 calculation/finding using a lookup table. I would like to know what is the polynomial used to generate those table values.
So given the table, how can I recover the polynomial? I tried using this nice calculator of tables, but cannot get the same values.
static const uint8_t crc_table[] = {
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31,
0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9,
0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1,
0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe,
0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16,
0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80,
0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8,
0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10,
0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f,
0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7,
0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef,
0xfa, 0xfd, 0xf4, 0xf3
};
uint8_t
crc8(uint8_t *p, uint8_t len)
{
uint16_t i;
uint16_t crc = 0x0;
while (len--) {
i = (crc ^ *p++) & 0xFF;
crc = (crc_table[i] ^ (crc << 8)) & 0xFF;
}
return crc & 0xFF;
}
Well, the link you provided shows the exact same table for the (default) polynomial 0x07, which is (x^8) + x^2 + x + 1. So this should already answer your question.
With the above being said, for a general "target" table, you can very easily brute force the needed polynomial.
I'll let the code speak for itself, here's a working example:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
static const uint8_t target[256] = {
// ... fill in the values here ...
};
void compute_table(uint8_t table[256], uint8_t polynomial) {
uint8_t crc = 0x80;
size_t i, j;
memset(table, 0, 256);
for (i = 1; i < 256; i <<= 1) {
if (crc & 0x80)
crc = (crc << 1) ^ polynomial;
else
crc <<= 1;
for (j = 0; j < i; j++)
table[i + j] = crc ^ table[j];
}
}
int main(void) {
uint8_t table[256];
uint8_t poly;
bool found;
size_t i;
for (poly = 1; poly != 0; poly++) {
compute_table(table, poly);
found = true;
for (i = 0; i < 256; i++) {
if (table[i] != target[i]) {
found = false;
break;
}
}
if (found)
printf("Found polynomial: 0x%02x\n", poly);
}
return 0;
}
And indeed, plugging in the table you provide, the above code outputs:
Found polynomial: 0x07
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
unsigned char table[256] = {0};
void crc_table_create(unsigned char *pdata, unsigned char factor)
{
unsigned char temp;
for (int i = 0; i < 256; i++)
{
pdata[i] = i;
}
for (int i = 0; i < 256; i++)
{
for (int j = 7; j >= 0; j--)
{
temp = pdata[i] & 0x80; // take the MSB bit
if (temp) // the MSB bit is 1
{
pdata[i] = pdata[i] << 1;
pdata[i] ^= factor;
}
else
{
pdata[i] = pdata[i] << 1;
}
}
// printf("table[%i]= 0x%02x", i, table[i]);
// getchar();
}
}
int main(void)
{
int i, j = 0;
uint8_t poly = 0x07; // X8 + X2 + X1 + 1 (100000111B the MSB bit is mute, so it turn to 0x07)
crc_table_create(table, poly);
for (i = 0; i < 256; i++)
{
if (i % 12 == 0) {
printf("\n");
}
printf("0x%02x, ", table[i]);
}
printf("\n");
return 1;
}
Here is the CRC8 table generater, after run it, the 'table[256]' is the result, enjoy!

Encryption Implementation - Confusing results

I'm trying to use simple encryption/decryption (treyfer) for a project of mine, but there's no reference implementation of decryption available. What I've got (based off of the Wikipedia implementation) is:
uint8_t rotl(uint8_t x) {
return (x << 1) | (x >> 7);
}
uint8_t rotr(uint8_t x) {
return (x >> 1) | (x << 7);
}
void encrypt (uint8_t text[8], uint8_t key[8]) {
int r, i;
uint8_t t;
for (r=0; r<NUMROUNDS; r++) {
text[8] = text[0];
for (i=0; i<8; i++) {
text[i+1] = rotl((text[i+1] + sbox[(key[i] + text[i]) % 256]));
}
text[0] = text[8];
}
}
void decrypt (uint8_t text[8], uint8_t key[8]) {
int r, i;
uint8_t t;
for (r=0; r<NUMROUNDS; r++) {
text[8] = text[0];
for (i=8; i>=0; --i) {
text[i+1] = rotr(text[i+1]) - sbox[(key[i] + text[i]) % 256];
}
text[0] = text[8];
}
}
void printhex(uint8_t text[8]) {
for(int i = 0; i < 8; i++) {
printf("%02x", text[i]);
}
}
int main() {
char text[8+1] = "AAAAAAAA";
char key[8+1] = "AAAAAAAA";
puts("plaintext:");
printhex(text);
puts("\nkey:");
printhex(key);
puts("\nencrypted:");
encrypt(text, key);
printhex(text);
puts("\ndecrypted:");
decrypt(text, key);
printhex(text);
}
Where Sbox is the AES S-box, and NUMROUNDS = 128
However, when I run this, I get wildly different results for the plaintext and the decrypted value, suggesting either my encryption or decryption is incorrect, but I can't quite see how. Hoping I haven't missed anything too painful.
The output I get is:
plaintext:
4141414141414141
key:
4141414141414141
encrypted:
658ed27d394127a0
decrypted:
a0460a65d755953f
I assume your implementation is based on this: https://en.wikipedia.org/wiki/Treyfer
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define NUMROUNDS 100
static const uint8_t sbox[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
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 };
void treyfer_encrypt(uint8_t text[8], uint8_t const key[8])
{
unsigned i;
uint8_t t = text[0];
for (i = 0; i < 8*NUMROUNDS; i++) {
t += key[i%8];
t = sbox[t] + text[(i+1)%8];
text[(i+1) % 8] = t = (t << 1) | (t >> 7); /* Rotate left 1 bit */
}
}
void encrypt(uint8_t text[8], uint8_t const key[8])
{
unsigned int i = 0;
unsigned int j = 0;
uint8_t t = 0;
t = text[0];
for (j = 0; j < NUMROUNDS; j++)
{
for (i = 0; i < 8; i++)
{
t = t + key[i];
t = sbox[t] + text[(i + 1) % 8];
t = (t << 1) | (t >> 7);
text[(i + 1) % 8] = t;
}
}
}
void decrypt(uint8_t text[8], uint8_t const key[8])
{
int i = 0;
int j = 0;
uint8_t top = 0;
uint8_t bottom = 0;
for (j = 0; j < NUMROUNDS; j++)
{
for (i = 7; i >= 0; i--)
{
top = text[i] + key[i];
top = sbox[top];
bottom = text[(i + 1) % 8];
bottom = (bottom >> 1) | (bottom << 7);
text[(i + 1) % 8] = bottom - top;
}
}
}
void printhex(uint8_t text[8]) {
int i;
for(i = 0; i < 8; i++) {
printf("%02x", text[i]);
}
}
int main() {
uint8_t text[8] = "AAAAAAAA";
uint8_t text2[8] = "AAAAAAAA";
uint8_t key[8] = "AAAAAAAA";
puts("plaintext:");
printhex(text);
puts("\nkey:");
printhex(key);
puts("\n\nref encrypted:");
treyfer_encrypt(text, key);
printhex(text);
puts("\n\nencrypted:");
encrypt(text2, key);
printhex(text2);
puts("\n\ndecrypted:");
decrypt(text2, key);
printhex(text2);
puts("\n");
}
results
plaintext:
4141414141414141
key:
4141414141414141
ref encrypted:
cc3121ccab578d93
encrypted:
cc3121ccab578d93
decrypted:
4141414141414141

Compiler error initializing array of structs in C (array must be initialized with a brace-enclosed initializer)

I'm stumped by the compiler error "error: array must be initialized with a brace-enclosed initializer". None of the other examples of this problem seem to related to this. I haven't touched C in about 14 years, so I think the term "rust" is a bit generous. I'm sure I've just missed something silly.
typedef uint8_t DeviceAddress[8];
DeviceAddress Probe01 = { 0x28, 0xFF, 0x87, 0x5A, 0x91, 0x15, 0x04, 0xE0 };
DeviceAddress Probe02 = { 0x28, 0xFF, 0x97, 0x5E, 0x91, 0x15, 0x04, 0x92 };
DeviceAddress Probe03 = { 0x28, 0xFF, 0xCD, 0x81, 0x91, 0x15, 0x01, 0x1E };
DeviceAddress Probe04 = { 0x28, 0xFF, 0xA6, 0x69, 0x91, 0x15, 0x04, 0x15 };
DeviceAddress Probe05 = { 0x28, 0xFF, 0xD8, 0x7E, 0x91, 0x15, 0x04, 0x64 };
struct DeviceInfo {
DeviceAddress addr;
const char * name;
};
struct DeviceInfo devices[5] = {
{.addr = Probe01, .name = "Pump1"},
{.addr = Probe02, .name = "Pump2"},
{.addr = Probe03, .name = "Pump3"},
{.addr = Probe04, .name = "Pump4"},
{.addr = Probe05, .name = "Pump5"}
};
struct DeviceInfo devices[5] = {
{.addr = Probe01, .name = "Pump1"},
{.addr = Probe02, .name = "Pump2"},
{.addr = Probe03, .name = "Pump3"},
{.addr = Probe04, .name = "Pump4"},
{.addr = Probe05, .name = "Pump5"}
};
Here, addr is of type DeviceAddress, which is just a uint8_t array. You can't assign into an array in C, so the compiler is telling you that assigning Probe1 into the field addr is invalid; it needs its own brace-enclosed array initializer there.
You have a couple of options. You could get rid of Probe01, Probe02, etc altogether and just initialize the arrays as the compiler suggests:
struct DeviceInfo devices[5] = {
{.addr = { 0x28, 0xFF, 0x87, 0x5A, 0x91, 0x15, 0x04, 0xE0 }, .name = "Pump1" },
...
};
Another option, which is a bit roundabout, is to have two typedefs:
typedef uint8_t DeviceAddress[8];
typedef uint8_t * DeviceAddress_P;
struct DeviceInfo {
DeviceAddress_P addr;
const char * name;
};
And use the pointer type in the struct, initializing it to point to the first element of the array you created:
DeviceAddress Probe01 = { 0x28, 0xFF, 0x87, 0x5A, 0x91, 0x15, 0x04, 0xE0 };
struct DeviceInfo devices[5] = {
{.addr = Probe01, .name = "Pump1"},
...
};
However, this way, the struct just points to an external array, which is probably not desirable.
If you use "Probe0x" just as helpers to make think clearer as asked by #M.M, you can initialise the array devices of type Struct DeviceInfo as fallow:
struct DeviceInfo devices[5] = {
{{ 0x28, 0xFF, 0x87, 0x5A, 0x91, 0x15, 0x04, 0xE0 }, "Pump1"},
{{ 0x28, 0xFF, 0x97, 0x5E, 0x91, 0x15, 0x04, 0x92 }, "Pump2"},
{{ 0x28, 0xFF, 0xCD, 0x81, 0x91, 0x15, 0x01, 0x1E }, "Pump3"},
{{ 0x28, 0xFF, 0xA6, 0x69, 0x91, 0x15, 0x04, 0x15 }, "Pump4"},
{{ 0x28, 0xFF, 0xD8, 0x7E, 0x91, 0x15, 0x04, 0x64 }, "Pump5"}
};

Resources