如何从 OpenSSL 中的 perl 脚本生成程序集文件

How the assembly file is generated from the perl script in OpenSSL

在 OpenSSL(版本 1.1.0e)的开源代码中,我看到一些函数定义是由文件夹中的 perl 文件生成的。 在 crypto 中每个文件夹中存在的 build.info 文件中,他们编写了一些行以从相应的 .pl 生成 .s。

例如,要在 crypto/aes/build.info 中生成 aes_p8_set_encrypt_key

GENERATE[aesp8-ppc.s]=asm/aesp8-ppc.pl $(PERLASM_SCHEME)

用于在 crypto/build.info 中生成 OPENSSL_madd300_probe :

GENERATE[ppccpuid.s]=ppccpuid.pl $(PERLASM_SCHEME)

而且在主 Makefile(生成的 makefile)中,有如下几行:

crypto/aes/aes-x86_64.o: crypto/aes/aes-x86_64.s
$(CC)  -I. -Icrypto/include -Iinclude $(CFLAGS) $(LIB_CFLAGS) -MMD -MF crypto/aes/aes-x86_64.d.tmp -MT $@ -c -o $@ crypto/aes/aes-x86_64.s
@touch crypto/aes/aes-x86_64.d.tmp
@if cmp crypto/aes/aes-x86_64.d.tmp crypto/aes/aes-x86_64.d > /dev/null 2> /dev/null; then \
    rm -f crypto/aes/aes-x86_64.d.tmp; \
else \
    mv crypto/aes/aes-x86_64.d.tmp crypto/aes/aes-x86_64.d; \
fi

后跟:

crypto/aes/aes-x86_64.s: crypto/aes/asm/aes-x86_64.pl
CC="$(CC)" $(PERL) crypto/aes/asm/aes-x86_64.pl $(PERLASM_SCHEME) $@

谁能解释一下 .s 是如何从 .pl 文件生成的? 我需要将它们添加到项目中的 Makefile 中,以解决定义由 .pl 文件生成的函数的 undefined reference 错误。

How the assembly file is generated from the Perl script in OpenSSL...

您正在 Power8 上使用 Cryptogams implementation AES。 Cryptogams 是 Andy Polyakov 的项目,旨在为其他开发人员提供高速密码学。

汇编语言文件是用xlat程序生成的。对于 Power8 齿轮,文件是 crypto/aes/asm 目录中的 ppc-xlate.pl in the perlasm directory. It is used by aesp8-ppc.pl

这是您翻译的方式。我在 GCC112 on the compile farm 工作,即 ppc64le。

git clone https://github.com/openssl/openssl.git
mkdir cryptogams

cp ./openssl/crypto/perlasm/ppc-xlate.pl cryptogams/
cp ./openssl/crypto/aes/asm/aesp8-ppc.pl cryptogams/

cd cryptogams/
chmod +x *.pl

./aesp8-ppc.pl ppc64le aesp8-ppc.s

aesp8-ppc.pl 生成一个纯汇编语言源文件,因此用小 *.s 命名输出文件。有时翻译包括 C 预处理器语句,它需要一个大的 *.S(但在这种情况下不是)。

aesp8-ppc.pl 的第二个参数称为 flavor。在上面的命令中是ppc64le。风味有两个作用。首先,它选择 32 位或 64 位。其次,它选择 little-endian 或 big-endian。一定要选对味道。

根据安迪在 ppc8 does not build on powerpc64 big-endian 的说法,big-endian PowerPC 应该使用 linux64,而不是 linux64be。然而,Little-endian 需要 linux64le

一旦你有了 aesp8-ppc.s 你就可以用 GCC 编译和 assemble 源文件。

gcc -mcpu=power8 -c aesp8-ppc.s

然后:

$ objdump --disassemble aesp8-ppc.o
aesp8-ppc.o:     file format elf64-powerpcle
...

0000000000000420 <aes_p8_set_decrypt_key>:
     420:       c1 ff 21 f8     stdu    r1,-64(r1)
     424:       a6 02 48 7d     mflr    r10
     428:       50 00 41 f9     std     r10,80(r1)
     42c:       75 fc ff 4b     bl      a0 <aes_p8_set_encrypt_key>
     430:       a6 03 48 7d     mtlr    r10
     434:       00 00 03 2c     cmpwi   r3,0
     438:       68 00 c2 40     bne-    4a0 <Ldec_key_abort>
     43c:       36 20 07 55     rlwinm  r7,r8,4,0,27
     440:       10 ff 65 38     addi    r3,r5,-240
     444:       7e f8 08 55     rlwinm  r8,r8,31,1,31
     448:       14 3a a3 7c     add     r5,r3,r7
     44c:       a6 03 09 7d     mtctr   r8
...

此时您有一个 object 文件,但您不知道 API 签名或如何使用它。要了解接下来要做什么,您必须 objdump 然后 grep OpenSSL 源以查看它们如何使用它。

$ nm aesp8-ppc.o | grep ' T '
00000000000006c0 T aes_p8_cbc_encrypt
0000000000001140 T aes_p8_ctr32_encrypt_blocks
00000000000005c0 T aes_p8_decrypt
00000000000004c0 T aes_p8_encrypt
0000000000000420 T aes_p8_set_decrypt_key
00000000000000a0 T aes_p8_set_encrypt_key
0000000000001d00 T aes_p8_xts_decrypt
0000000000001a60 T aes_p8_xts_encrypt

您对 aes_p8_set_encrypt_keyaes_p8_set_decrypt_keyaes_p8_encryptaes_p8_decrypt 这四个函数感兴趣。您将使用找到的签名为您的程序创建 header 文件。

我会帮你做第一个:aes_p8_set_encrypt_key

$ cd openssl

# Find aes_p8_set_encrypt_key
$ grep -nIR aes_p8_set_encrypt_key
crypto/evp/e_aes.c:153:# define HWAES_set_encrypt_key aes_p8_set_encrypt_key

# Now look for HWAES_set_encrypt_key
$ grep -nIR HWAES_set_encrypt_key
...
crypto/evp/e_aes.c:2515:int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
...

# Now find the complete HWAES_set_encrypt_key
$ cat -n crypto/evp/e_aes.c
...
  2515  int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
  2516                            AES_KEY *key);

起泡、冲洗,重复 AES_KEYaes_p8_set_decrypt_keyaes_p8_encryptaes_p8_decrypt

最终你会得到一个 header,如 Cryptogams | AES or Cryptogams | SHA on the OpenSSL wiki. Cryptogams | AES and Cryptogams | SHA 所示,是为 ARMv4 编写的,但同样适用于 Power8。


Andy 双重许可他的作品。一个许可证是 OpenSSL 许可证,因为 Andy 为 OpenSSL 工作。第二个许可证是 BSD 风格的许可证,没有 OpenSSL 的障碍。

Andy 的 public 来源在 GitHub | dot-asm。不幸的是,Andy 的很多工作还没有上传,所以你必须从 OpenSSL 中提取它。很多它没有记录在案,因此您必须在 OpenSSL 源代码中进行大量的探索和刺激。

据我所知,您可以在两个地方查找有关使用 Cryptogams 和 Power8 密码术的文档。首先是 OpenSSL wiki 页面 Cryptogams | AES and Cryptogams | SHA。这些教程是 ARMv4,但它也适用于 Power 8。我写了 wiki 文章,所以错误和遗漏是我的错误。

第二个要看的地方是GitHub和Noloader | POWER8 crypto。我帮助维护 Crypto++,POWER8 加密书籍是我的知识转储。 POWER8 书籍在第 7 章中包含用于 PowerPC 的 Cryptogams SHA。

POWER8 加密书籍由 Bill Schmidt 和我编写,因为在 Power8 上使用 AES 和 SHA 时我们找不到文档。 Bill Schmidt 为 IBM 工作,甚至他也无法获得文档。我们所能找到的只是一位 IBM 工程师的博客 post,其中严重缺少详细信息。