我能够遵循代码路径到某个点。 简要:
- 该程序接受 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
功能在哪里?
这句话似乎是我的越橘:
# 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
此功能的文档?
以下是一些解释令牌串联的文档。您也可以将此作为关于在哪里系统地搜索可靠文档的建议:
-
C 标准。在这个网站上,你可以下载WG14 N1570,它与C11标准非常相似(它是一个试行标准草案,但它与标准基本相同,只是你不必为此付费。http://port70.net/~nsz/c/c11/n1570.html 有一个 HTML 版本的文档,它对于构建链接很方便。考虑到这一点,我可以向您指出该标准§6.10.3.3中
##
的实际标准定义。 -
如果你还不是 C 方面的专家,C 标准可能会有点粗糙。它对学习者的让步很少。一个更具可读性的文档是 Gnu GCC 的 C 预处理器 (CPP( 手册,尽管它并不总是区分标准功能和 GCC 扩展。尽管如此,它仍然具有很强的可读性,并且有很多有用的信息。第 3.5 章中解释了
##
运算符 -
cppreference.com 更广为人知的是C++参考站点,但它也包含有关 C 的文档。它的语言几乎和C++/C标准一样电报,并不总是100%准确(虽然它非常好(,但它有几个优点。首先,它结合了不同标准版本的文档,因此它对于了解功能何时进入该语言(以及因此您需要使用该功能的编译器版本(非常有用。此外,它交联良好,因此非常易于导航。以下是它对预处理器的看法;您可以在此处找到有关
##
的文档。
我已经这样做了一段时间,但我开始清楚,在aeskey.c
文件的预处理宏中正在进行模式匹配。 我唯一能找到的文档就是这个。
模式匹配
##
运算符用于将两个令牌连接成一个令牌。这 IS 提供了一种非常强大的模式匹配方法。说我们想 编写一个IIF
宏,我们可以这样写:#define IIF(cond) IIF_ ## cond #define IIF_0(t, f) f #define IIF_1(t, f) t
但是,这种方法存在一个问题。微妙的副作用
##
运算符是它抑制膨胀。下面是一个示例:#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)
解决此问题的方法是使用另一个间接寻址。从此 通常,我们可以编写一个名为
CAT
的宏来连接 没有抑制。#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
所以现在我们可以编写
IIF
宏(现在称为IIF
,稍后我们 将展示如何定义定义IF
的更通用方法 宏(:#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)
通过模式匹配,我们可以定义其他操作,例如
COMPL
它采取补充:#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) #define COMPL_0 1 #define COMPL_1 0
或
BITAND
:#define BITAND(x) PRIMITIVE_CAT(BITAND_, x) #define BITAND_0(y) 0 #define BITAND_1(y) y
我们可以将递增和递减运算符定义为宏:
#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