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

标签 c openssl undefined-reference powerpc

在 OpenSSL(版本 1.1.0e)的开源代码中,我看到一些函数定义是由文件夹中存在的 perl 文件生成的。 在加密货币内每个文件夹中的 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...

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

汇编语言文件是用 xlat 程序生成的。对于 Power8 齿轮,文件为 ppc-xlate.plperlasm 目录中。它由 aesp8-ppc.pl 使用在crypto/aes/asm目录中。

这是您的翻译方式。我的工作地点是 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 位。其次,它选择小端字节序或大端字节序。确保味道正确。

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

一旦有了aesp8-ppc.s,您就可以使用GCC编译和汇编源文件。

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

此时您已经有了一个目标文件,但您不知道 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 这四个函数感兴趣。您将使用找到的签名为您的程序创建头文件。

我将帮助您完成第一个: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

最终你会得到一个像 Cryptogams | AES 所示的标题。或Cryptogams | SHA在 OpenSSL 维基上。 Cryptogams | AESCryptogams | SHA是为 ARMv4 编写的,但同样也适用于 Power8。

<小时/>

安迪拥有他的作品的双重许可。一种许可证是 OpenSSL 许可证,因为 Andy 为 OpenSSL 工作。第二个许可证是 BSD 样式许可证,没有 OpenSSL 的阻碍。

Andy 的公共(public)源位于 GitHub | dot-asm 。不幸的是,Andy 的很多作品尚未上传,因此您必须从 OpenSSL 中提取它。而且很多内容都没有记录在案,因此您必须在 OpenSSL 源代码中进行大量的研究。

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

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

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

关于c - 如何从 OpenSSL 中的 perl 脚本生成程序集文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46322246/

相关文章:

c - mariadb c api windows undefined reference to

c - 通过轮询非阻塞套接字正确处理 EWOULDBLOCK

c - 在堆栈上分配大型数组时出现段错误

c++ - 如何在没有 p、q 等的情况下加载 RSA key 对

ssl - phpmailer、requre() 和 include_path 合并

c++ - 什么是 undefined reference /未解析的外部符号错误,我该如何解决?

c - 链接器错误 undefined reference to `print'

c - 使用 C 也将变量字符串分配给数组

c - 预处理的 printf 函数

go - 如何在Go中解密使用Openssl aes-256-cbc加密的文件