【问题标题】:Import Windows Certificate Store CRLs into OpenSSL将 Windows 证书存储 CRL 导入 OpenSSL
【发布时间】:2016-11-30 18:03:44
【问题描述】:

我在 Windows 中使用 OpenSSL。我想要 OpenSSL 的证书检查来根据他们的 CRL 验证证书。在 OpenSSL 文档中,它说:

如果启用 CRL 检查,则 CRL 应在相应的 X509_STORE 结构中可用。不会尝试从 CRL 分发点扩展下载 CRL。

我使用 Windows 证书存储中的证书填充 OpenSSL 的证书存储。我想对 Windows 证书存储中存在的 CRL 做同样的事情。

有没有办法做到这一点? OpenSSL 是否有可能在其检查中添加了 CRL 下载但尚未记录在案?

【问题讨论】:

    标签: windows ssl openssl


    【解决方案1】:

    事实证明这比我想象的要容易得多 - 您使用 CertEnumCRLsInStore 获取相关商店的 CRL,然后使用 d2i_X509_CRL 对 OpenSSL 的证书进行编码。整个事情与此非常相似:https://stackoverflow.com/a/40046425/1132699

    【讨论】:

    • 它仅枚举显式安装 CRL。有没有办法从 Windows 证书存储的缓存中获取 CRL?
    【解决方案2】:

    我编写了以下代码来实现按需从缓存中获取 CRL:

    #define length_of(x) (sizeof(x) / sizeof(x[0]))
    #define length_of_null_terminated_string(x) (length_of(x) - 1)
    
    static X509_CRL * GetCRLByUrl(
        const char * url)
    {
        PCCRL_CONTEXT pCrlContext = nullptr;
        BOOL res = ::CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CRL, 0, 0, (LPVOID*)&pCrlContext, nullptr, nullptr, nullptr, nullptr);
        if (!res) {
            DWORD dwErr = ::GetLastError();
            return nullptr;
        }
    
        const unsigned char * pbCrlEncoded = pCrlContext->pbCrlEncoded;
        X509_CRL * x509_crl = d2i_X509_CRL(NULL, &pbCrlEncoded, pCrlContext->cbCrlEncoded);
        ::CertFreeCRLContext(pCrlContext);
        if (!x509_crl) {
            return nullptr;
        }
    
        return x509_crl;
    
        LOG_SCOPE_LEAVE;
    }
    
    static STACK_OF(X509_CRL) * LookupCRLsInWindowsStore(
        X509_STORE_CTX * ctx,
        X509_NAME * nm)
    {
        STACK_OF(X509_CRL) * crls = sk_X509_CRL_new_null();
        if (!crls) {
            return nullptr;
        }
    
        X509 * x509 = X509_STORE_CTX_get_current_cert(ctx);
    
        static int nids[] = { NID_crl_distribution_points, NID_freshest_crl };
        for (int * it = std::begin(nids), * itEnd = std::end(nids); it != itEnd; ++it) {
            int nid = *it;
            STACK_OF(DIST_POINT) * crldp = (STACK_OF(DIST_POINT) *)X509_get_ext_d2i(x509, nid, NULL, NULL);
            for (int i = 0, iEnd = sk_DIST_POINT_num(crldp); i < iEnd; ++i) {
                DIST_POINT * dp = sk_DIST_POINT_value(crldp, i);
                if (!dp->distpoint) {
                    continue;
                }
                if (dp->distpoint->type != 0) {
                    continue;
                }
    
                GENERAL_NAMES * gens = dp->distpoint->name.fullname;
                for (int j = 0, jEnd = sk_GENERAL_NAME_num(gens); j < jEnd; ++j) {
                    GENERAL_NAME * gen = sk_GENERAL_NAME_value(gens, i);
                    int gtype;
                    ASN1_STRING * uri = (ASN1_STRING *)GENERAL_NAME_get0_value(gen, &gtype);
                    if (gtype != GEN_URI) {
                        continue;
                    }
                    const char * url = (const char *)ASN1_STRING_data(uri);
                    if (ASN1_STRING_length(uri) < length_of_null_terminated_string("http://") || strncmp(url, "http://", length_of_null_terminated_string("http://")) != 0) {
                        continue;
                    }
                    X509_CRL * x509_crl = GetCRLByUrl(url);
                    if (x509_crl) {
                        sk_X509_CRL_push(crls, x509_crl);
                        break;
                    }
                }
            }
            sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
        }
    
        return crls;
    }
    
    X509_STORE * x509_store = ...;
    X509_STORE_set_lookup_crls_cb(x509_store, LookupCRLsInWindowsStore);
    

    【讨论】:

    • 我假设您从 openssl 的 s_client 应用程序中派生代码...与您的 LookupCRLsInWindowsStore() 例程相反,如果@987654325,他们的回调 crls_http_cb() 总是获取增量 CRL(NID_freshest_crl 分发点) @ 分发点存在。
    猜你喜欢
    • 2013-03-18
    • 1970-01-01
    • 2014-05-10
    • 2020-06-26
    • 2016-02-17
    • 2021-08-04
    • 2011-12-16
    • 2019-01-29
    • 1970-01-01
    相关资源
    最近更新 更多