如果原因是“未指定”,CertGetCertificateChain 无法识别吊销的证书

信息安全 视窗 证书吊销
2021-09-04 12:29:23

在我的程序中,我CertGetCertificateChain用来调查证书的有效性。如果在我的测试 PKI 中我撤销证书并指定原因“未指定”,则最后一个参数中的错误代码pChainContext->TrustStatus.dwErrorStatus为零,表示没有错误,证书不被视为已撤销。但是,在 Windows 事件日志中,我可以看到以下条目:

ETW 未指定

因此,撤销及其原因得到了正确检测,但CertGetCertificateChain并没有让我知道。

如果我以任何其他原因(例如“停止操作”)撤销证书,则CertGetCertificateChain正确返回pChainContext->TrustStatus.dwErrorStatus == 4这意味着CERT_TRUST_IS_REVOKED并且在 Windows 事件日志中我可以看到:

ETW 停止运营

所以我的问题是:这种行为CertGetCertificateChain正确吗?

我花了一些时间研究这个,我发现了这个文件在第 6.3.2 (a) 节中,它说:

原因掩码:此变量包含到目前为止处理的 CRL 和增量 CRL 支持的撤销原因集。该集合的合法成员是可能的撤销原因值减去未指定的值:keyCompromise、cACompromise、affiliationChanged、superseded、cessationOfOperation、certificateHold、privilegeWithdrawn 和 aACompromise。特殊值 all-reasons 用于表示所有合法成员的集合。这个变量被初始化为空集。

(重点是我的)

另一方面,在下一段 6.3.2 (b) 中它说:

cert_status:此变量包含证书的状态。此变量可以分配以下值之一:unspecified、keyCompromise、cACompromise、affiliationChanged、superseded、cessationOfOperation、certificateHold、removeFromCRL、privilegeWithdrawn、aACompromise、特殊值 UNREVOKED 或特殊值 UNDETERMINED。此变量被初始化为特殊值 UNREVOKED。

我真的不知道如何解释这一点。这是否意味着所描述的算法不能因为未在掩码中设置而将“未指定”原因视为已撤销?如果是这样,这将意味着CertGetCertificateChain行为正确。但随后出现了一些后续问题:难道不应该有一些大写的、闪烁的警告吗?

“如果您撤销证书,永远不要选择“未指定”作为原因,否则不会被视为撤销。”?

但也许我没有正确阅读这个,所以这里有一些我的其他盲目猜测为什么CertGetCertificateChain不能像预期的那样工作:

  • 也许我需要配置我的 CRL 以支持“未指定”的原因。但我看不到在哪里可以配置它。
  • 我是否必须传递一些额外的标志才能CertGetCertificateChain使其考虑“未指定”的原因?我看不到任何听起来合适的标志...
  • 我是否试图解决一个不存在的问题?也许实际上没有人使用“未指定”的原因,这就是为什么我发现关于它的信息如此之少?

任何人都可以对此有所了解吗?

1个回答

我对证书吊销列表的经验几乎为零,因此在某些地方我可能在技术上不正确。这个答案完全基于我阅读 RFC5280 相关部分的理解。


所以我的问题是:这种行为CertGetCertificateChain正确吗?

显然,是的。

主要原因很简单,您不应该将 CRL 中的原因设置为unspecifiedRFC 的第 5.3.1 节说

但是,原因代码 CRL 条目扩展应该不存在,而不是使用未指定 (0) 的原因代码值。


关于您对第 6.3.2 节中两个明显矛盾的段落的混淆......这些实际上是指 CRL 处理算法中使用的两个独立变量:reasons_maskcert_status.

reasons_mask变量旨在包含到目前为止处理的 CRL 的支持吊销原因,因此在很大程度上与算法是否将证书视为已吊销无关。如果我理解正确,此变量用于确保在 CRL设置了标志的情况下(这意味着 CRL 仅包含出于其指定原因的撤销),算法将检查来自证书颁发者的其他 CRL 以涵盖其他撤销原因。onlySomeReasons

cert_status变量是与您的问题相关的变量。此变量初始化为UNREVOKED当根据 CRL 检查证书时,如果找到与证书颁发者和序列号匹配的条目,则cert_status使用以下规则(来自 RFC)进行设置:

(1) 如果存在原因码 CRL 条目扩展,请将 cert_status 变量设置为原因码 CRL 扩展的值。

(2) 如果原因码 CRL 条目扩展不存在,请将 cert_status 变量设置为未指定的值。

因此,如果存在原因代码 CRL 条目扩展,则cert_status应该将其设置为与给定原因代码相对应的原因。但是,未指定的原因代码无效,因此,在您的情况下,Microsoft 的实现可能只是cert_status保留它已经存在的内容(在这种情况下UNREVOKED)。这导致CertGetCertificateChain认为证书有效。