OpenSSL PKCS#11签署多个进程

时间:2014-03-12 10:05:50

标签: c++ openssl sigsegv pkcs#11

我正在调试某人为某个应用程序编写的php模块中的分段错误(因此改变工作流程和其他耗时的操作是不可能的)。

我有以下代码: ...

...some code... int marker=0; ENGINE_load_dynamic(); ENGINE *e=ENGINE_by_id("dynamic"); if (e==NULL) return NULL; ...some more code to set some parameters using ENGINE_ctrl_cmd_string(...)

marker++; // gets about 10 or something e=ENGINE_by_id("pkcs11"); if (e==NULL) return NULL;

这里有趣的部分 - SIGSEGV:

marker++; //11 if (!ENGINE_init(e)){ std::cout<<"..error.."; ENGINE_finish(e); ENGINE_free(e); ENGINE_cleanup(); return null; }

...code using pkcs#11 token that does work....

问题以随机的方式出现,有点像。该片段是php模块的一部分。该脚本是从PostgreSQL脚本调用的,而PostgreSQL脚本又由另一个驻留在另一台服务器上的php应用程序调用(不要因为这个设计而责备我,我在这里调试)。当我快速刷新主php应用程序页面时出现SIGSEGV,我认为它同时多次调用上述脚本,因此尝试同时使用来自不同进程的令牌。

我的假设是否正确?可以使用相同的令牌冲突从单独的进程调用ENGINE_init / finish / free并导致分段错误吗?

使用我的处理程序捕获分段错误,该处理程序获取标记值并在退出之前打印它,这是我可以为sigsegv调试提出的最简单的方法。如果这种方法可能会产生错误的结果,我会很感激通知。

有什么想法?

1 个答案:

答案 0 :(得分:0)

有一个 README.ENGINE ,它提供了对引擎的讨论。我不确定它会有多大用处,因为它会有一些很高的要求。例如,“......源代码相当好的自我记录,但需要一些摘要和使用说明”。

但这是dynamic上的内容:

  

新的“动态”ENGINE提供了一种低开销的支持方式   未预编译和链接到的ENGINE实现   基于OpenSSL的应用程序。这可能是因为存在   编译实现已知问题,您希望使用   具有现有应用程序的较新版本。它同样可以   因为您正在使用的应用程序(或OpenSSL库)   不支持您要使用的ENGINE和ENGINE   提供商(例如硬件供应商)正在为您提供   共享库形式的自包含实现。该   “动态”的其他用例是希望用于的应用程序   保持最小的足迹,因此不要链接   来自OpenSSL的各种ENGINE实现,但是离开了你   如果你想要它们,以“动态” - 可加载的形式提供它们   共享库。硬件供应商应该可以   提供自己的共享库来支持任意硬件   使用基于OpenSSL 0.9.7或更高版本的应用程序。如果你是   使用基于0.9.7(或更高版本)的应用程序并为您提供支持   欲望仅在您需要的版本之后发布,   要求供应商将他们的ENGINE反向移植到您需要的版本。

     

“动态”如何运作?

The dynamic ENGINE has a special flag in its implementation such that
every time application code asks for the 'dynamic' ENGINE, it in fact
gets its own copy of it. As such, multi-threaded code (or code that
multiplexes multiple uses of 'dynamic' in a single application in any
way at all) does not get confused by 'dynamic' being used to do many
independent things. Other ENGINEs typically don't do this so there is
only ever 1 ENGINE structure of its type (and reference counts are used
to keep order). The dynamic ENGINE itself provides absolutely no
cryptographic functionality, and any attempt to "initialise" the ENGINE
automatically fails. All it does provide are a few "control commands"
that can be used to control how it will load an external ENGINE
implementation from a shared-library. To see these control commands,
use the command-line;

   openssl engine -vvvv dynamic

The "SO_PATH" control command should be used to identify the
shared-library that contains the ENGINE implementation, and "NO_VCHECK"
might possibly be useful if there is a minor version conflict and you
(or a vendor helpdesk) is convinced you can safely ignore it.
"ID" is probably only needed if a shared-library implements
multiple ENGINEs, but if you know the engine id you expect to be using,
it doesn't hurt to specify it (and this provides a sanity check if
nothing else). "LIST_ADD" is only required if you actually wish the
loaded ENGINE to be discoverable by application code later on using the
ENGINE's "id". For most applications, this isn't necessary - but some
application authors may have nifty reasons for using it. The "LOAD"
command is the only one that takes no parameters and is the command
that uses the settings from any previous commands to actually *load*
the shared-library ENGINE implementation. If this command succeeds, the
(copy of the) 'dynamic' ENGINE will magically morph into the ENGINE
that has been loaded from the shared-library. As such, any control
commands supported by the loaded ENGINE could then be executed as per
normal. Eg. if ENGINE "foo" is implemented in the shared-library
"libfoo.so" and it supports some special control command "CMD_FOO", the
following code would load and use it (NB: obviously this code has no
error checking);

   ENGINE *e = ENGINE_by_id("dynamic");
   ENGINE_ctrl_cmd_string(e, "SO_PATH", "/lib/libfoo.so", 0);
   ENGINE_ctrl_cmd_string(e, "ID", "foo", 0);
   ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
   ENGINE_ctrl_cmd_string(e, "CMD_FOO", "some input data", 0);

For testing, the "openssl engine" utility can be useful for this sort
of thing. For example the above code excerpt would achieve much the
same result as;

   openssl engine dynamic \
             -pre SO_PATH:/lib/libfoo.so \
             -pre ID:foo \
             -pre LOAD \
             -pre "CMD_FOO:some input data"

Or to simply see the list of commands supported by the "foo" ENGINE;

   openssl engine -vvvv dynamic \
             -pre SO_PATH:/lib/libfoo.so \
             -pre ID:foo \
             -pre LOAD

Applications that support the ENGINE API and more specifically, the
"control commands" mechanism, will provide some way for you to pass
such commands through to ENGINEs. As such, you would select "dynamic"
as the ENGINE to use, and the parameters/commands you pass would
control the *actual* ENGINE used. Each command is actually a name-value
pair and the value can sometimes be omitted (eg. the "LOAD" command).
Whilst the syntax demonstrated in "openssl engine" uses a colon to
separate the command name from the value, applications may provide
their own syntax for making that separation (eg. a win32 registry
key-value pair may be used by some applications). The reason for the
"-pre" syntax in the "openssl engine" utility is that some commands
might be issued to an ENGINE *after* it has been initialised for use.
Eg. if an ENGINE implementation requires a smart-card to be inserted
during initialisation (or a PIN to be typed, or whatever), there may be
a control command you can issue afterwards to "forget" the smart-card
so that additional initialisation is no longer possible. In
applications such as web-servers, where potentially volatile code may
run on the same host system, this may provide some arguable security
value. In such a case, the command would be passed to the ENGINE after
it has been initialised for use, and so the "-post" switch would be
used instead. Applications may provide a different syntax for
supporting this distinction, and some may simply not provide it at all
("-pre" is almost always what you're after, in reality).