Pre-processor macro to convert an hex string to a byte array

喜夏-厌秋 提交于 2019-12-13 14:50:26

问题


I've defined an AES-128 key as a build symbol inside my IDE, so that it calls GCC like this:

arm-none-eabi-gcc -D"AES_KEY=3B7116E69E222295163FF1CAA1681FAC" ...

(which is equivalent to #define AES_KEY 3B7116E69E222295163FF1CAA1681FAC)

The advantage is that the same symbol can also be passed automatically as a parameter to a post-build CLI script that encrypts the compiled code with this key (e.g. for a secure firmware update)...

But how to store this key as a byte array in my code? I would like to define a pre-processor macro which does the conversion:

uint8_t aes_key[] = { SPLIT_MACRO(AES_KEY) };

to

uint8_t aes_key[] = {0x3B, 0x71, 0x16, 0xE6, 0x9E, 0x22, 0x22, 0x95, ...};

In other words, could the GCC pre-processor split the key string in 2-char blocks and add ", 0x" between them?


回答1:


A bit clumsy, but if you know the length of your key in advance you could approach it as follows:

  1. define a macro HEXTONIBBLE that translates a hex digit into a number
  2. define a macro HEXTOBYTE that uses HEXTONIBBLE to get a byte from a hex
  3. initialize your array with HEXTOBYTE parameterized correctrly

If your KEY is not in form of a string, i.e. enclosed in double quotes, then use the stringify-operator # (with a trick using a variadic macro in order to expand a macro when used as parameter or another one):

//           01234567890123456789012345678901
#define K    3B7116E69E222295163FF1CAA1681FAC

#define STRINGIFY_HELPER(A) #A
#define STRINGIFY(...) STRINGIFY_HELPER(__VA_ARGS__)

#define KEY  STRINGIFY(K)

#define HEXTONIBBLE(c) (*(c) >= 'A' ? (*(c) - 'A')+10 : (*(c)-'0'))

#define HEXTOBYTE(c) (HEXTONIBBLE(c)*16 + HEXTONIBBLE(c+1))

uint8_t aes_key[] = {
    HEXTOBYTE(KEY+0),
    HEXTOBYTE(KEY+2),
    HEXTOBYTE(KEY+4),
    HEXTOBYTE(KEY+6),
    HEXTOBYTE(KEY+8),
    HEXTOBYTE(KEY+10),
    HEXTOBYTE(KEY+12),
    HEXTOBYTE(KEY+14),
    HEXTOBYTE(KEY+16),
    HEXTOBYTE(KEY+18),
    HEXTOBYTE(KEY+20),
    HEXTOBYTE(KEY+22),
    HEXTOBYTE(KEY+24),
    HEXTOBYTE(KEY+26),
    HEXTOBYTE(KEY+28),
    HEXTOBYTE(KEY+30)
};

int main() {

    for (int i=0; i<sizeof(aes_key); i++) {
        printf("%02X ", aes_key[i]);
    }

    return 0;
}

Output:

3B 71 16 E6 9E 22 22 95 16 3F F1 CA A1 68 1F AC 



回答2:


This does not answer the original question but if the key can be written in this format instead:

#define AES_KEY 3B,71,16,E6,9E,22,22,95,16,3F,F1,CA,A1,68,1F,AC

The following macro will work, even under GCC:

#define BA(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) {0x##a,0x##b,0x##c,0x##d,\
0x##e,0x##f,0x##g,0x##h,0x##i,0x##j,0x##k,0x##l,0x##m,0x##n,0x##o,0x##p}

#define TO_BYTEARRAY(...) BA(__VA_ARGS__)

uint8_t aes_key[] = TO_BYTEARRAY(AES_KEY);

See Concatenation, Argument Prescan and Variadic Macros



来源:https://stackoverflow.com/questions/45848866/pre-processor-macro-to-convert-an-hex-string-to-a-byte-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!