在 Brian Gladman 的 AES 实现中,aes_encrypt_key128 是如何映射到 aes_xi 的?

In Brian Gladman's AES implementation, how is aes_encrypt_key128 being mapped to aes_xi?

我能够遵循代码路径直到某个点。简要地说:

  1. 该程序接受 ASCII 十六进制字符串并将其转换为二进制。 https://github.com/BrianGladman/aes/blob/master/aesxam.c#L366-L382
  2. 如果 arg[3] 是一个“E”,它定义了一个 aes_encrypt_ctx 结构并将键、计算出的 key_len 值和 aes_encrypt_ctx 结构传递给 aes_encrypt_keyhttps://github.com/BrianGladman/aes/blob/master/aesxam.c#L409-L412
  3. aes_encrypt_keyaeskey.c 中定义。根据 key_len,函数 aes_encrypt_key<NNN> 被调用。它们的键和结构被传递给函数。 https://github.com/BrianGladman/aes/blob/master/aeskey.c#L545-L547

但是 aes_encrypt_key128 函数的地方?

这个line appears to be my huckleberry:

#  define aes_xi(x) aes_ ## x

希望我有所作为。它正在将 aes_encrypt_key128 映射到 aes_xi(encrypt_key128),对吗?

AES_RETURN aes_xi(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1])
{   uint32_t    ss[4];

    cx->ks[0] = ss[0] = word_in(key, 0);
    cx->ks[1] = ss[1] = word_in(key, 1);
    cx->ks[2] = ss[2] = word_in(key, 2);
    cx->ks[3] = ss[3] = word_in(key, 3);

#ifdef ENC_KS_UNROLL
    ke4(cx->ks, 0);  ke4(cx->ks, 1);
    ke4(cx->ks, 2);  ke4(cx->ks, 3);
    ke4(cx->ks, 4);  ke4(cx->ks, 5);
    ke4(cx->ks, 6);  ke4(cx->ks, 7);
    ke4(cx->ks, 8);
#else
    {   uint32_t i;
        for(i = 0; i < 9; ++i)
            ke4(cx->ks, i);
    }
#endif
    ke4(cx->ks, 9);
    cx->inf.l = 0;
    cx->inf.b[0] = 10 * AES_BLOCK_SIZE;

#ifdef USE_VIA_ACE_IF_PRESENT
    if(VIA_ACE_AVAILABLE)
        cx->inf.b[1] = 0xff;
#endif
    MARK_AS_ENCRYPTION_CTX(cx);
    return EXIT_SUCCESS;
}

我看到这里发生了一些模式替换。我想在这一点上我想知道你是否可以指点我解释 #define?

的这个特性的文档

我已经有一段时间了,但我开始清楚 aeskey.c 文件的预处理宏中正在进行模式匹配。我能找到的唯一文档是 this one.

Pattern Matching

The ## operator is used to concatenate two tokens into one token. This is provides a very powerful way to do pattern matching. Say we want to write a IIF macro, we could write it like this:

#define IIF(cond) IIF_ ## cond
#define IIF_0(t, f) f
#define IIF_1(t, f) t

However there is one problem with this approach. A subtle side effect of the ## operator is that it inhibits expansion. Heres an example:

#define A() 1
//This correctly expands to true
IIF(1)(true, false)
// This will however expand to
IIF_A()(true, false)
// This is because A() doesn't expand to 1,
// because its inhibited by the ## operator
IIF(A())(true, false) 

The way to work around this is to use another indirection. Since this is commonly done we can write a macro called CAT that will concatenate without inhibition.

#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__

So now we can write the IIF macro (its called IIF right now, later we will show how to define a more generalized way of defining an IF macro):

#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t

#define A() 1
//This correctly expands to true
IIF(1)(true, false)
// And this will also now correctly expand to true
IIF(A())(true, false) 

With pattern matching we can define other operations, such as COMPL which takes the complement:

#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0

or BITAND:

#define BITAND(x) PRIMITIVE_CAT(BITAND_, x)
#define BITAND_0(y) 0
#define BITAND_1(y) y

We can define increment and decrement operators as macros:

#define INC(x) PRIMITIVE_CAT(INC_, x)
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INC_9 9

#define DEC(x) PRIMITIVE_CAT(DEC_, x)
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8

这里有一些解释令牌连接的文档。您也可以将此作为有关在哪里系统地搜索可靠文档的建议:

  1. C 标准。在this website you can download WG14 N1570, which is quite similar to the C11 standard (it's a pre-standard draft, but it's basically the same as the standard except you don't have to pay for it.) There's an HTML version of this document at http://port70.net/~nsz/c/c11/n1570.html, which is handy for constructing links. With that in mind, I can point you at the actual standard definition of ## in §6.10.3.3的标准。

  2. 如果您还不是 C 方面的专家,C 标准可能会有些粗糙。它对学习者的让步很少。更具可读性的文档是 Gnu GCC 的 C Preprocessor (CPP) manual, although it is does not always distinguish between standard features and GCC extensions. Still, it's quite readable and there's lots of useful information. The ## operator is explained in Chapter 3.5

  3. cppreference.com is better known as a C++ reference site, but it also contains documentation about C. It's language is almost as telegraphic as the C++/C standards, and it is not always 100% accurate (although it is very good), but it has several advantages. For one thing, it combines documentation for different standard versions, so it is really useful for knowing when a feature entered the language (and consequently which compiler version you will need to use the feature). Also, it is well cross-linked, so it's very easy to navigate. Here's what it has to say about the preprocessor; you'll find documentation about ## here.