Macro de préprocesseur permettant de convertir une chaîne hexadécimale en un tableau d’octets

J’ai défini une clé AES-128 en tant que symbole de construction dans mon IDE, de sorte qu’elle appelle GCC de la manière suivante:

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

(ce qui équivaut à #define AES_KEY 3B7116E69E222295163FF1CAA1681FAC )

L’avantage est que le même symbole peut également être transmis automatiquement en tant que paramètre à un script CLI post-génération qui chiffre le code compilé avec cette clé (par exemple, pour une mise à jour de firmware sécurisée) …

Mais comment stocker cette clé sous forme de tableau d’octets dans mon code? Je voudrais définir une macro pré-processeur qui effectue la conversion:

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

à

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

En d’autres termes, le pré-processeur GCC pourrait-il fractionner la chaîne de clé en blocs de 2 caractères et append ” , 0x ” entre eux?

Un peu maladroit, mais si vous connaissez la longueur de votre clé à l’avance, vous pouvez l’approcher comme suit:

  1. définir une macro HEXTONIBBLE qui traduit un chiffre hexadécimal en un nombre
  2. définir une macro HEXTOBYTE qui utilise HEXTONIBBLE pour obtenir un octet d’un hex
  3. initialiser votre tableau avec HEXTOBYTE paramétré correctement

Si votre KEY n’est pas sous la forme d’une chaîne, c’est-à-dire entre guillemets, utilisez l’opérateur ssortingngify-operator # (avec une astuce utilisant une macro variadique afin de développer une macro lorsqu’elle est utilisée en tant que paramètre ou une autre):

 // 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 

Sortie:

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

Cela ne répond pas à la question initiale mais si la clé peut être écrite dans ce format:

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

La macro suivante fonctionnera même sous 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); 

Voir Concaténation , Argument Prescan et Macros Variadic