在 Brian Gladman 的 AES 实现中,aes_encrypt_key128 是如何映射到 aes_xi 的?
In Brian Gladman's AES implementation, how is aes_encrypt_key128 being mapped to aes_xi?
我能够遵循代码路径直到某个点。简要地说:
- 该程序接受 ASCII 十六进制字符串并将其转换为二进制。 https://github.com/BrianGladman/aes/blob/master/aesxam.c#L366-L382
- 如果
arg[3]
是一个“E”,它定义了一个 aes_encrypt_ctx
结构并将键、计算出的 key_len
值和 aes_encrypt_ctx
结构传递给 aes_encrypt_key
。 https://github.com/BrianGladman/aes/blob/master/aesxam.c#L409-L412
aes_encrypt_key
在 aeskey.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
这里有一些解释令牌连接的文档。您也可以将此作为有关在哪里系统地搜索可靠文档的建议:
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的标准。
如果您还不是 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
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.
我能够遵循代码路径直到某个点。简要地说:
- 该程序接受 ASCII 十六进制字符串并将其转换为二进制。 https://github.com/BrianGladman/aes/blob/master/aesxam.c#L366-L382
- 如果
arg[3]
是一个“E”,它定义了一个aes_encrypt_ctx
结构并将键、计算出的key_len
值和aes_encrypt_ctx
结构传递给aes_encrypt_key
。 https://github.com/BrianGladman/aes/blob/master/aesxam.c#L409-L412 aes_encrypt_key
在aeskey.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 aIIF
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 calledIIF
right now, later we will show how to define a more generalized way of defining anIF
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
这里有一些解释令牌连接的文档。您也可以将此作为有关在哪里系统地搜索可靠文档的建议:
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的标准。如果您还不是 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.5cppreference.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.