从OpenSSL-1.0.1r中删除OPENSSL_cleanse
我发现OPENSSL_cleanse
在我的项目中浪费了很多时间。 例如,如果它运行25秒,则OPENSSL_cleanse
会浪费3秒 。 我检查了这个函数的代码,并确定它没有对我做任何非常有用的事情。 我知道它出于安全原因用垃圾数据填充内存,但我并不真正关心它。 所以我决定return;
就在此函数的任何操作开始之前。
void OPENSSL_cleanse(void *ptr, size_t len) { return; // original OpenSSL code goes here }
我正在使用Mac OS和Xcode。 我编译了lib并通过Configure
脚本的--openssldir
选项将其安装在/Users/ForceBru/Desktop/openssl
。 我已经在Build Settings->Link Binary With Libraries
中将它添加到我的项目中,并在Build Settings->Search Paths->Header Search Paths
和Build Settings->Search Paths->Library Search Paths
添加了dirs。
该项目编译得很好,但时间分析器仍显示对OPENSSL_cleanse
相当昂贵的调用。
编辑: C
标签是因为OpenSSL是用C++
编写的,而C++
标签是因为我的代码是用C ++编写的。 也许这些信息会有所帮助。
问题是,我做错了什么? 如何删除对OPENSSL_cleanse
的调用? 我认为这与链接有关,因为命令行包含-lcrypto
,这意味着这个库实际上可以从任何地方获取(对吗?),而不一定来自/Users/ForceBru/Desktop/openssl
。
编辑#2:我编辑了链接器选项以使用/Users/ForceBru/Desktop/openssl
的.a
文件,并将其从Build Settings->Link Binary With Libraries
删除。 仍然没有效果。
事实certificate,OpenSSL有许多汇编代码,这些代码由位于crypto
目录( *cpuid.pl
)中的一些Perl脚本生成。 这些脚本为以下体系结构生成汇编代码: alpha
, armv4
, ia64
, ppc
, s390x
, sparc
, x86
和x86_64
。
当make
运行时,相应的脚本将触发生成*cpuid.S
(其中*
是前面提到的体系结构之一)。 这些文件被编译到库中,似乎覆盖了crypto/mem_clr.c
实现的crypto/mem_clr.c
。
我要做的就是简单地将OPENSSL_cleanse
的主体更改为x86_64cpuid.pl
:
.globl OPENSSL_cleanse .type OPENSSL_cleanse,\@abi-omnipotent .align 16 OPENSSL_cleanse: ret # loads of OPENSSL assembly .size OPENSSL_cleanse,.-OPENSSL_cleanse
这不是你想要的答案,但它可以帮助你…
从OpenSSL-1.0.1r中删除OPENSSL_cleanse …
我检查了这个函数的代码,并确定它没有对我做任何非常有用的事情……
这可能是一个坏主意,但我们需要更多地了解您的威胁模型。 归零允许您确定性地从内存中删除敏感材料。
它也是一个认证和认证(C&A)项目。 例如, FIPS 140-2即使在1级也需要归零。
此外,你不能删除OPENSSL_cleanse
本身因为OPENSSL_clear_realloc
, OPENSSL_clear_free
和朋友调用它。 另请参见OPENSSL_cleanse
手册页。
例如,如果它运行25秒,则OPENSSL_cleanse会浪费3秒
好的,所以这是一个不同的问题。 OPENSSL_cleanse有点复杂,它确实浪费了一些周期来努力在优化过程中存活下来。
如果您检查Commit 380f18ed5f140e0a ,那么您将在OpenSSL 1.1.0中看到它已更改为以下内容。 也许你可以用它代替?
diff --git a/crypto/mem_clr.cb/crypto/mem_clr.c index e6450a1..3389919 100644 (file) --- a/crypto/mem_clr.c +++ b/crypto/mem_clr.c @@ -59,23 +59,16 @@ #include #include -extern unsigned char cleanse_ctr; -unsigned char cleanse_ctr = 0; +/* + * Pointer to memset is volatile so that compiler must de-reference + * the pointer and can't assume that it points to any function in + * particular (such as memset, which it then might further "optimize") + */ +typedef void *(*memset_t)(void *,int,size_t); + +static volatile memset_t memset_func = memset; void OPENSSL_cleanse(void *ptr, size_t len) { - unsigned char *p = ptr; - size_t loop = len, ctr = cleanse_ctr; - - if (ptr == NULL) - return; - - while (loop--) { - *(p++) = (unsigned char)ctr; - ctr += (17 + ((size_t)p & 0xF)); - } - p = memchr(ptr, (unsigned char)ctr, len); - if (p) - ctr += (63 + (size_t)p); - cleanse_ctr = (unsigned char)ctr; + memset_func(ptr, 0, len); }
另请参见问题455:在OpenSSL的GitHub上重新实现非asm OPENSSL_cleanse() 。
如何删除对OPENSSL_cleanse的调用?
好的,所以这是一个不同的问题。 您必须找到所有呼叫者并对每个呼叫者执行某些操作。 看起来你需要修改大约185个地方:
$ cd openssl $ grep -IR _cleanse * | wc -l 185
而不是这个:
void OPENSSL_cleanse(void *ptr, size_t len) { return; // original OpenSSL code goes here }
也许你可以删除该function,然后:
#define OPENSSL_cleanse(x, y)
然后函数调用变成一个在优化过程中消失的宏。 从函数更改为宏后,请务必执行make clean
。
但我不建议这样做。
该项目编译得很好,但时间分析器仍显示对OPENSSL_cleanse的相当昂贵的调用。
我的猜测是(1)您在更改OpenSSL库后没有执行make clean
,或者(2)您编译并链接到错误版本的OpenSSL库。 但我两个都错了。
您可以使用otool -L
查看可执行文件的运行时依赖otool -L
。 确保它是预期的。 还要记住,OpenSSL不使用-install_name
。
在运行可执行文件之前,可以设置DYLD_LIBRARY_PATH以确保加载要修改的dylib。 另请参见dyld(1)手册页。