扩展 CertOpenStore 功能

证书存储是所有证书管理操作的核心。 CertOpenStore 函数的功能可以通过使用可安装 (或注册的) certificate-store-provider 函数来扩展。 有关如何安装或注册用于 CryptoAPI 的函数的概述,请参阅 OID 概述

注意

执行自动部署时,不会自动迁移自定义证书存储。 若要迁移自定义证书存储,必须创建用于迁移自定义存储的清单,并使用 Windows 用户状态迁移工具 (USMT) 。

 

CertOpenStore 在内存中打开一个空存储,如果使用在 lpszStoreProvider 参数中传递的 OID) 对象标识符) (注册或安装存储提供程序函数, (调用存储提供程序函数。 有关使用 CryptoAPI 提供的预定义提供程序类型的列表,请参阅 CertOpenStore

存储提供程序函数将其证书和 证书吊销列表 (CRL) 复制到由传递给它的 hCertStore 句柄指定的内存中存储。 新的存储提供程序函数可以使用任何 CryptoAPI 证书存储函数(如 CertAddCertificateContextToStoreCertAddSerializedElementToStore)将其证书和 CRL 添加到内存中存储。 此外,store-provider 函数可以选择性地返回 CERT_STORE_PROV_INFO 结构的所有数据成员的值。 仅当函数支持其他回调函数时,函数才需要更新此结构。 例如,如果存储区是只读存储区,则可能不需要支持其他回调函数。 有关可能的回调函数的详细信息和原型,请参阅 证书存储提供程序回调函数

每用户 TrustedPeople 存储仅限于预定义的物理存储。 不能扩展每用户 TrustedPeople 存储。 但是,可以扩展本地计算机 TrustedPeople 存储。

Windows XP 和 Windows Server 2003: Per user TrustedPeople 存储不限于预定义的物理存储。

CERT_STORE_PROV_INFO 结构的数据成员之一是 rgpvStoreProvFunc 数组。 如果存储提供程序函数需要支持一个或多个回调函数,则必须为此数组提供指针。 这些指针必须指向要用于其他证书存储活动的回调函数 (,例如关闭存储) 。 下图显示了此过程的流程。

certopenstore 功能

如下图所示,打开存储后,其他 CryptoAPI 函数(如 CertCloseStore ) () 使用指针数组来访问执行预期任务的回调函数。 CERT_STORE_PROV_INFO 结构的定义和随 CryptoAPI 一起提供的默认回调函数的原型显示在证书存储提供程序回调函数中。

certclosestore 功能

存储 API 允许存储提供程序在存储 (缓存外部维护证书、CRL 和 证书信任列表 (CTL) ,例如,证书的外部数据库(例如 Microsoft 证书服务器数据库) 提供)。

CertOpenStore 通过 pszStoreProvider 参数调度到相应的 CertDllOpenStoreProv 可安装提供程序函数。 提供程序返回 pStoreProvInfo 参数中指向 CERT_STORE_PROV_INFO 结构的信息。 CERT_STORE_PROV_INFO 结构包含 dwStoreProvFlags 成员。 添加了CERT_STORE_PROV_EXTERNAL_FLAG标志以允许提供程序指示证书、CRL 和 CTL 位于存储缓存的外部。

CertDllOpenStoreProv 返回回调函数数组。 提供程序可以实现以下回调函数:

  • CERT_STORE_PROV_CLOSE_FUNC
  • CERT_STORE_PROV_READ_CERT_FUNC
  • CERT_STORE_PROV_WRITE_CERT_FUNC
  • CERT_STORE_PROV_DELETE_CERT_FUNC
  • CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC
  • CERT_STORE_PROV_READ_CRL_FUNC
  • CERT_STORE_PROV_WRITE_CRL_FUNC
  • CERT_STORE_PROV_DELETE_CRL_FUNC
  • CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC
  • CERT_STORE_PROV_READ_CTL_FUNC
  • CERT_STORE_PROV_WRITE_CTL_FUNC
  • CERT_STORE_PROV_DELETE_CTL_FUNC
  • CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC

在设置CERT_STORE_PROV_WRITE_ADD_FLAG时调用WRITE_CERT、WRITE_CRL和WRITE_CTL回调函数时, dwFlags 参数的上 16 位包含 dwAddDisposition 值。 若要支持外部存储,提供程序可以实现以下回调函数:

  • CERT_STORE_PROV_FIND_CERT_FUNC
  • CERT_STORE_PROV_FREE_FIND_CERT_FUNC
  • CERT_STORE_PROV_GET_CERT_PROPERTY_FUNC
  • CERT_STORE_PROV_FIND_CRL_FUNC
  • CERT_STORE_PROV_FREE_FIND_CRL_FUNC
  • CERT_STORE_PROV_GET_CRL_PROPERTY_FUNC
  • CERT_STORE_PROV_FIND_CTL_FUNC
  • CERT_STORE_PROV_FREE_FIND_CTL_FUNC
  • CERT_STORE_PROV_GET_CTL_PROPERTY_FUNC

证书回调函数具有以下签名:

typedef struct _CERT_STORE_PROV_FIND_INFO {
    DWORD               cbSize;
    DWORD               dwMsgAndCertEncodingType;
    DWORD               dwFindFlags;
    DWORD               dwFindType;
    const void          *pvFindPara;
} CERT_STORE_PROV_FIND_INFO, *PCERT_STORE_PROV_FIND_INFO;
typedef const CERT_STORE_PROV_FIND_INFO CCERT_STORE_PROV_FIND_INFO,
    *PCCERT_STORE_PROV_FIND_INFO;

typedef BOOL (WINAPI *PFN_CERT_STORE_PROV_FIND_CERT)(
        IN HCERTSTOREPROV hStoreProv,
        IN PCCERT_STORE_PROV_FIND_INFO pFindInfo,
        IN PCCERT_CONTEXT pPrevCertContext,
        IN DWORD dwFlags,
        IN OUT void **ppvStoreProvFindInfo,
        OUT PCCERT_CONTEXT *ppProvCertContext
        );

typedef BOOL (WINAPI *PFN_CERT_STORE_PROV_FREE_FIND_CERT)(
        IN HCERTSTOREPROV hStoreProv,
        IN PCCERT_CONTEXT pCertContext,
        IN void *pvStoreProvFindInfo,
        IN DWORD dwFlags
        );

typedef BOOL (WINAPI *PFN_CERT_STORE_PROV_GET_CERT_PROPERTY)(
        IN HCERTSTOREPROV hStoreProv,
        IN PCCERT_CONTEXT pCertContext,
        IN DWORD dwPropId,
        IN DWORD dwFlags,
        OUT void *pvData,
        IN OUT DWORD *pcbData
        );

CRL 和 CTL 回调函数的签名与上述相同,指向 CERT_CONTEXT 的指针替换为指向 CRL_CONTEXTCTL_CONTEXT的指针。

当存储 API 枚举、查找或添加证书时,将调用FIND_CERT回调。 pPrevCertContextppvStoreProvFindInfo 设置为 NULL 以启动新的 FIND。 返回的 ppvStoreProvFindInfo 将在下一次查找时传递回,届时提供程序可能会释放该 ppvStoreProvFindInfo。 提供程序可以设置所有、部分或全部证书属性。 提供程序可以选择延迟到调用GET_CERT_PROPERTY回调。 建议提供程序设置尽可能多的属性,以允许复制到另一个存储。

CertFindCertificateInStore 支持以下证书查找类型:

  • CERT_FIND_ANY
  • CERT_FIND_SHA1_HASH
  • CERT_FIND_MD5_HASH
  • CERT_FIND_PROPERTY
  • CERT_FIND_PUBLIC_KEY
  • CERT_FIND_SUBJECT_NAME
  • CERT_FIND_SUBJECT_ATTR
  • CERT_FIND_ISSUER_NAME
  • CERT_FIND_ISSUER_ATTR
  • CERT_FIND_SUBJECT_STR_A
  • CERT_FIND_SUBJECT_STR_W
  • CERT_FIND_ISSUER_STR_A
  • CERT_FIND_ISSUER_STR_W
  • CERT_FIND_KEY_SPEC
  • CERT_FIND_ENHKEY_USAGE

对于上述每个查找类型,都会调用FIND_CERT回调。 在调用FIND_CERT回调之前,传递给 CertFindCertificateInStore 的参数将直接复制到 CERT_STORE_PROV_FIND_INFO 结构。 有关不同查找类型CERT_STORE_PROV_FIND_INFO结构的字段值的详细信息,请参阅 CertFindCertificateInStore

以下证书查找类型支持 CertGetSubjectCertificateFromStoreCertGetIssuerCertificateFromStore API,并帮助确定证书是否已存在于存储中,然后再添加:

  • CERT_FIND_SUBJECT_CERT
  • CERT_FIND_ISSUER_OF
  • CERT_FIND_EXISTING

对于CERT_FIND_SUBJECT_CERT, pvFindPara 参数指向包含主题的 Issuer 和 SerialNumber 的CERT_INFO 结构。 对于CERT_FIND_ISSUER_OF, pvFindPara 指向主题 CERT_CONTEXT 结构。 对于CERT_FIND_EXISTING,pvFindPara 指向证书CERT_CONTEXT,以检查存储中是否存在证书。

当FIND_CERT回调返回的证书未在后续的下一个FIND_CERT中使用时调用FREE_FIND_CERT回调,从而使其 引用计数 减少到零,或通过调用 CertCloseStore 释放。 在调用 CLOSE 回调之前,FIND_CERT回调返回的所有证书都应通过传递给对FIND_CERT回调的调用或对FREE_FIND_CERT回调的调用来释放给提供程序。 这同样适用于 CRL 和 CTL 回调。

如果 CertGetCertificateContextProperty 找不到 pCertContext 参数的指定属性,则 CertGetCertificateContextProperty 将调用GET_CERT_PROPERTY回调。 GET_CRL_PROPERTY和GET_CTL_PROPERTY也是如此。

当存储 API 枚举或获取 CRL 时,在添加 CRL 之前调用FIND_CRL回调。 将定义以下 CRL 查找类型:

对于 CRL_FIND_ISSUED_BY, pvFindPara 是指向 CRL 颁发者的 CERT_CONTEXT 的指针。 对于CRL_FIND_EXISTING, pvFindPara 是指向 CRL CRL_CONTEXT 的指针,用于确定它是否已存在于存储区中。

当存储 API 枚举或查找 CTL 时,将调用FIND_CTL回调。 CertFindCTLInStore 支持以下 CTL 查找类型:

  • CTL_FIND_ANY
  • CTL_FIND_SHA1_HASH
  • CTL_FIND_MD5_HASH
  • CTL_FIND_USAGE
  • CTL_FIND_SUBJECT
  • CTL_FIND_EXISTING

对上述每种查找类型调用FIND_CTL回调。 在调用FIND_CTL回调之前,传递给 CertFindCTLInStore 的参数将直接复制到 CERT_STORE_PROV_FIND_INFO 结构。 有关CERT_STORE_PROV_FIND_INFO结构的不同查找类型的字段值的详细信息,请参阅 CertFindCTLInStore

CTL_FIND_EXISTING CTL 查找类型有助于确定在执行 CTL 添加之前存储中是否已存在 CTL。

对于CTL_FIND_EXISTING, pvFindPara 是指向 CTL CTL_CONTEXT 结构的指针,用于确定它是否已存在于存储中。