locked
How to determine whether a certificate is CA or End Entity programatically RRS feed

  • Question

  • Is there any api available to check to whether a certificate is CA or End Entity.

    I know that the checking of cert basic constraint may be use ful.

    It could be very helpful to get some sample or apis to check the CA or End Entity from cert context.

    About, CertVerifyCertificateChainPolicy a little bit of confusion in the description of CERT_CHAIN_POLICY_BASIC_CONSTRAINTS.

    Tuesday, August 4, 2020 6:54 AM

Answers

  • For is CA, you could try the following sample:

    bool IsCACert(PCCERT_CONTEXT pCertContext_i) { for (int i = 0; i < pCertContext_i->pCertInfo->cExtension; i++) { if (strcmp(pCertContext_i->pCertInfo->rgExtension[i].pszObjId, szOID_BASIC_CONSTRAINTS2)==0) { CERT_BASIC_CONSTRAINTS2_INFO info = { 0 }; DWORD size = sizeof(CERT_BASIC_CONSTRAINTS2_INFO); CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2, pCertContext_i->pCertInfo->rgExtension[i].Value.pbData, pCertContext_i->pCertInfo->rgExtension[i].Value.cbData, 0, &info, &size); return info.fCA; } }

    return FALSE;

    }

    Best Regards,

    Drake

    This “Windows Desktop SDK” Forum will be migrating to a new home on Microsoft Q&A, please refer to this sticky post for more details. 


    "Win32 API" forum will be migrating to a new home on Microsoft Q&A !
    We invite you to post new questions in the "Win32 API" forum’s new home on Microsoft Q&A !
    For more information, please refer to the sticky post.

    Wednesday, August 5, 2020 7:53 AM
  • Thank you for the prompt reply and its worked.

    i.e

    1. acquire a CERT_CONTEXT of the certificate

    2. navigate to pCertInfo of the CERT_CONTEXT structure.

    3. Iterate over extensions in rgExtension field of CERT_INFO extension

    4. Find extension with pszObjId equals to "2.5.29.19"

    5. if found, read extension value to CERT_BASIC_CONSTRAINTS2_INFO and read fCA field. If fCA is set to True, it is CA certificate. In all other cases it is end entity certificate.

    Wednesday, August 5, 2020 10:03 AM

All replies

  • Hi.

    Thanks for posting here.

    According to the CERT_CHAIN_POLICY_BASIC_CONSTRAINTSthe api will iterates through all the certificates in the chain, and if there is a szOID_BASIC_CONSTRAINTS or a szOID_BASIC_CONSTRAINTS2 extension, check if the first certificate element match the BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_CA_FLAG/BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_END_ENTITY_FLAG you specified in the `pPolicyPara->dwFlags`(Note that the [In]/[Out] attributes of the function parameters are: CertVerifyCertificateChainPolicy(_In_, _In_, _In_, _Inout_)). You need to specify the type you want to verify, if you also specify CA or End Entity flag). If you specified both or neither of them, then, the first element can be either a CA or END_ENTITY.

    Best Regards,

    Drake

    This “Windows Desktop SDK” Forum will be migrating to a new home on Microsoft Q&A, please refer to this sticky post for more details. 


    "Win32 API" forum will be migrating to a new home on Microsoft Q&A !
    We invite you to post new questions in the "Win32 API" forum’s new home on Microsoft Q&A !
    For more information, please refer to the sticky post.

    Wednesday, August 5, 2020 3:30 AM
  • Thanks for the reply. Still some unclear points exist. Can you check the below code.

    //to check whether a certificate is CA or not.
    bool IsCACert(PCCERT_CONTEXT pCertContext_i)
    {
    
    	CERT_CHAIN_ENGINE_CONFIG    EngineConfig = { 0 };
    	EngineConfig.cbSize = sizeof(EngineConfig);
    	EngineConfig.dwUrlRetrievalTimeout = 0;
    	HCERTCHAINENGINE            hChainEngine = NULL;
    	if(!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
    	{
    		std::cout << "Failed:CertCreateCertificateChainEngine\n";
    		return false;
    	}
    
    	CERT_CHAIN_PARA             ChainPara = { 0 };
    	ChainPara.cbSize = sizeof(ChainPara);
    	PCCERT_CHAIN_CONTEXT  pChainContext;
    	if (FALSE == CertGetCertificateChain(hChainEngine, pCertContext_i, NULL, NULL, &ChainPara, NULL, NULL, &pChainContext))
    	{
    		std::cout << "Failed:CertGetCertificateChain\n";
    		return false;
    	}
    
    	CERT_CHAIN_POLICY_PARA PolicyParam;
    	PolicyParam.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
    	PolicyParam.dwFlags = BASIC_CONSTRAINTS_CERT_CHAIN_POLICY_CA_FLAG;
    	CERT_CHAIN_POLICY_STATUS PolicyStatus;
    	if (FALSE == CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASIC_CONSTRAINTS, pChainContext, &PolicyParam, &PolicyStatus))
    	{
    		std::cout << "Failed:CertVerifyCertificateChainPolicy\n";
    		return false;
    	}
    	if (S_OK == PolicyStatus.dwError)
    	{
    		//std::cout << "CA certs.....\n";
    		return true;
    	}
    	std::cout << "End certs.....\n";
    	return false;
    }


    Wednesday, August 5, 2020 5:32 AM
  • For is CA, you could try the following sample:

    bool IsCACert(PCCERT_CONTEXT pCertContext_i) { for (int i = 0; i < pCertContext_i->pCertInfo->cExtension; i++) { if (strcmp(pCertContext_i->pCertInfo->rgExtension[i].pszObjId, szOID_BASIC_CONSTRAINTS2)==0) { CERT_BASIC_CONSTRAINTS2_INFO info = { 0 }; DWORD size = sizeof(CERT_BASIC_CONSTRAINTS2_INFO); CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2, pCertContext_i->pCertInfo->rgExtension[i].Value.pbData, pCertContext_i->pCertInfo->rgExtension[i].Value.cbData, 0, &info, &size); return info.fCA; } }

    return FALSE;

    }

    Best Regards,

    Drake

    This “Windows Desktop SDK” Forum will be migrating to a new home on Microsoft Q&A, please refer to this sticky post for more details. 


    "Win32 API" forum will be migrating to a new home on Microsoft Q&A !
    We invite you to post new questions in the "Win32 API" forum’s new home on Microsoft Q&A !
    For more information, please refer to the sticky post.

    Wednesday, August 5, 2020 7:53 AM
  • Thank you for the prompt reply and its worked.

    i.e

    1. acquire a CERT_CONTEXT of the certificate

    2. navigate to pCertInfo of the CERT_CONTEXT structure.

    3. Iterate over extensions in rgExtension field of CERT_INFO extension

    4. Find extension with pszObjId equals to "2.5.29.19"

    5. if found, read extension value to CERT_BASIC_CONSTRAINTS2_INFO and read fCA field. If fCA is set to True, it is CA certificate. In all other cases it is end entity certificate.

    Wednesday, August 5, 2020 10:03 AM
  • one more doubt..

    Hope the now the common cert type is V3. If older versions, the above logic fails. Right?

    Whether I need to consider X509_BASIC_CONSTRAINTS, szOID_BASIC_CONSTRAINTS, X509_BASIC_CONSTRAINTS2, szOID_BASIC_CONSTRAINTS2, all these oids?

    Hope only need to consider szOID_BASIC_CONSTRAINTS2 as others are obsolete.



    Wednesday, August 5, 2020 10:12 AM