c语言 - 在Brian Gladman的AES实现中,aes_encrypt_key128如何映射到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_key。 https://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功能在哪里

这句话似乎是我的越橘:

#  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此功能的文档?

以下是一些解释令牌串联的文档。您也可以将此作为关于在哪里系统地搜索可靠文档的建议:

  1. C 标准。在这个网站上,你可以下载WG14 N1570,它与C11标准非常相似(它是一个试行标准草案,但它与标准基本相同,只是你不必为此付费。http://port70.net/~nsz/c/c11/n1570.html 有一个 HTML 版本的文档,它对于构建链接很方便。考虑到这一点,我可以向您指出该标准§6.10.3.3中##的实际标准定义。

  2. 如果你还不是 C 方面的专家,C 标准可能会有点粗糙。它对学习者的让步很少。一个更具可读性的文档是 Gnu GCC 的 C 预处理器 (CPP( 手册,尽管它并不总是区分标准功能和 GCC 扩展。尽管如此,它仍然具有很强的可读性,并且有很多有用的信息。第 3.5 章中解释了##运算符

  3. 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

最新更新