OpenSSL and CAPI - collisions in certificates

时间:2018-08-22 13:48:38

标签: ssl openssl certificate collision

I am running into collision problems with the CAPI engine for OpenSSL: In a normal case, I am able to use a private key stored on my smartcard to establish a SSL connection using OpenSSL. Simplified code:

    EVP_PKEY pkey = ENGINE_load_private_key(my_engine, subject_name, 0, 0);
    void * pdata = my_certificate_context.pbCertEncoded;
    X509 * cert = d2i_X509(0, &pdata, my_certificate_context.cbCertEncoded);
    SSL_CTX_use_certificate(my_ssl_context, cert);
    SSL_CTX_use_private_key(my_ssl_context, pkey);

There is, however, a catch: If it happens that I have more than one certificate with the given Subject Name, the CAPI engine will select one of the certificates and it's up to luck whether it selects the correct one. Fortunately for me, it selected the wrong one and this way alerted me to the problem. Looking at the source codes, it looks like the CAPI engine supports more complex key-searching schemes, so that I could specify that the Subject Name is supposed to be found in a specific certificate store. I can get the certificate store's name easily since I have the proper PCCERT_CONTEXT, but I can't figure out how to tell the CAPI engine to use that certificate store. The documentation is extremely sketchy here and I failed to find a single example. I expect it can be done using FENGINE_ctrl_cmd_string, but I have no idea how to do it. Can anyone help me with this, please?

1 个答案:

答案 0 :(得分:1)

经过大量的研究和测试,我可以得出结论,可以使用 ENGINE_ctrl_cmd_string 更详细地指定证书的位置:

if (!ENGINE_ctrl_cmd_string(Engine, "store_name", "MY", 0)) printf("Failed!");
if (!ENGINE_ctrl_cmd_string(Engine, "store_flags", "1", 0)) printf("Failed!");

第一行告诉CAPI引擎使用其他证书存储(在这种情况下为“ MY”,但可以使用任何其他存储,例如“ ROOT”)。第二行指示引擎使用本地计算机存储,而不是当前用户。

但是:

1)这两个值对于引擎都是全局的。如果需要使用具有不同设置的多个同时连接,则每个连接必须具有单独的引擎。与在网上写的相反,使用 SSL_CTX_set_client_cert_engine 函数可以实现 。在这种情况下,您不需要将引擎设置为默认值。 (注意:如果我使用两个设置不同的两个引擎同时进行连接,我需要做一些实际的测试。到目前为止,它看起来仍然可以工作,但是我不确定。)

2)无法指定其他商店位置,例如当前服务商店。这将需要更新CAPI引擎。

3)无法使用更精确的标识来指定证书,例如通过指定哈希或序列号。

4)无论如何都指定一个证书是没有意义的,因为SSL引擎将忽略此类规范(实际上使用 SSL_CTX_use_certificate SSL_CTX_use_PrivateKey 功能所做的任何事情)。而是在执行握手时,它将打开由命令字符串指定的存储,并搜索由服务器选择的CA签名的证书。我不确定如果找到多个这样的证书会发生什么,我怀疑向用户显示了一个对话框。无论如何,除非您想修改引擎的插件,否则不可能通过代码选择特定的证书。 (注意:如果要在服务器端使用证书,则可能不是这种情况。)

5)使用功能 SSL_CTX_use_certificate SSL_CTX_use_PrivateKey 不仅毫无意义,而且实际上很危险,因为后者会选择第一个匹配的证书(例如,使用相同的使用者名称)在存储区中并使用它,而不考虑颁发CA或其他任何内容。

此信息对OpenSSL的1.0.2分支有效。我没有对新旧分支进行任何测试。