Upravit

Sdílet prostřednictvím


Example C Program: Creating a Certificate Chain

The following example creates and installs a nondefault certificate chain engine. The engine is used to build certificate chains for each of the certificates in a certificate store.

This example illustrates the following tasks and CryptoAPI functions:

#pragma comment(lib, "crypt32.lib")

#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>

void MyHandleError(char *s);

void main(void)
{
//---------------------------------------------------------
// Copyright (C) Microsoft.  All rights reserved.
// Declare and initialize variables.

HCERTCHAINENGINE         hChainEngine;
CERT_CHAIN_ENGINE_CONFIG ChainConfig;
PCCERT_CHAIN_CONTEXT     pChainContext;
PCCERT_CHAIN_CONTEXT     pDupContext;
HCERTSTORE               hCertStore;
PCCERT_CONTEXT           pCertContext = NULL;
CERT_ENHKEY_USAGE        EnhkeyUsage;
CERT_USAGE_MATCH         CertUsage;  
CERT_CHAIN_PARA          ChainPara;
DWORD                    dwFlags=0;
LPWSTR                   pszNameString;



//---------------------------------------------------------
// Initialize data structures.

if(!(pszNameString=(LPWSTR)malloc(256)))
    MyHandleError("Memory allocation failed.");
EnhkeyUsage.cUsageIdentifier = 0;
EnhkeyUsage.rgpszUsageIdentifier=NULL;
CertUsage.dwType = USAGE_MATCH_TYPE_AND;
CertUsage.Usage  = EnhkeyUsage;
ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
ChainPara.RequestedUsage=CertUsage;

ChainConfig.cbSize = sizeof(CERT_CHAIN_ENGINE_CONFIG);
ChainConfig.hRestrictedRoot= NULL ;
ChainConfig.hRestrictedTrust= NULL ;
ChainConfig.hRestrictedOther= NULL ;
ChainConfig.cAdditionalStore=0 ;
ChainConfig.rghAdditionalStore = NULL ;
ChainConfig.dwFlags = CERT_CHAIN_CACHE_END_CERT;
ChainConfig.dwUrlRetrievalTimeout= 0 ;
ChainConfig.MaximumCachedCertificates=0 ;
ChainConfig.CycleDetectionModulus = 0;

//---------------------------------------------------------
// Create the nondefault certificate chain engine.

if(CertCreateCertificateChainEngine(
         &ChainConfig,
         &hChainEngine))
{
    printf("A chain engine has been created.\n");
}
else
{
    MyHandleError("The engine creation function failed.");
}
// Open the My system store.

if(hCertStore=CertOpenSystemStore(NULL,L"MY"))
{
       printf("The MY Store is open.\n");
}
else
{
       MyHandleError("The MY system store did not open.");
}

//-------------------------------------------------------
// Loop through the certificates in the store, 
// and create a chain for each.

while(pCertContext = CertEnumCertificatesInStore(
             hCertStore,
             pCertContext))
{
//-------------------------------------------------------------------
// Get and display the name of subject of the certificate.

if(CertGetNameString(   
   pCertContext,   
   CERT_NAME_SIMPLE_DISPLAY_TYPE,   
   0,
   NULL,   
   pszNameString,   
   128))
{
   printf("\nCertificate for %s found.\n",pszNameString);
}
else
{
   MyHandleError("CertGetName failed.");
}

//-------------------------------------------------------------------
// Build a chain using CertGetCertificateChain
// and the certificate retrieved.

if(CertGetCertificateChain(
    NULL,                  // use the default chain engine
    pCertContext,          // pointer to the end certificate
    NULL,                  // use the default time
    NULL,                  // search no additional stores
    &ChainPara,            // use AND logic and enhanced key usage 
                           //  as indicated in the ChainPara 
                           //  data structure
    dwFlags,
    NULL,                  // currently reserved
    &pChainContext))       // return a pointer to the chain created
{
    printf("The chain has been created. \n");
}
else
{
    MyHandleError("The chain could not be created.");
}

//---------------------------------------------------------------
// Display some of the contents of the chain.

printf("The size of the chain context "
       "is %d. \n",pChainContext->cbSize);
printf("%d simple chains found.\n",pChainContext->cChain);
printf("\nError status for the chain:\n");

DWORD errorStatus = pChainContext->TrustStatus->dwErrorStatus;

if((errorStatus & CERT_TRUST_IS_NOT_TIME_VALID) != 0)
{
    printf("This certificate or one of the certificates in the "
         "certificate chain is not time-valid.\n");
}
if((errorStatus & CERT_TRUST_IS_REVOKED) != 0)
{
    printf("Trust for this certificate or one of the certificates "
         "in the certificate chain has been revoked.\n");
}
if((errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID) != 0)
{
    printf("The certificate or one of the certificates in the "
         "certificate chain does not have a valid signature.\n");
}
if((errorStatus & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) != 0)
{
    printf("The certificate or certificate chain is not valid "
         "in its proposed usage.\n");
}
if((errorStatus & CERT_TRUST_IS_UNTRUSTED_ROOT) != 0)
{
    printf("The certificate or certificate chain is based "
         "on an untrusted root.\n");
}
if((errorStatus & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) != 0)
{
    printf("The revocation status of the certificate or one of the"
         "certificates in the certificate chain is unknown.\n");
}
if((errorStatus & CERT_TRUST_IS_CYCLIC) != 0)
{
    printf("One of the certificates in the chain was issued by a "
         "certification authority that the original certificate "
         "had certified.\n");
}
if((errorStatus & CERT_TRUST_IS_PARTIAL_CHAIN) != 0)
{
    printf("The certificate chain is not complete.\n");
}
if((errorStatus & CERT_TRUST_CTL_IS_NOT_TIME_VALID) != 0)
{
    printf("A CTL used to create this chain was not time-valid.\n");
}
if((errorStatus & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) != 0)
{
    printf("A CTL used to create this chain did not have a valid "
         "signature.\n");
}
if((errorStatus & CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) != 0)
{
    printf("A CTL used to create this chain did not have a valid "
         "signature.\n");
}
else // CERT_TRUST_NO_ERROR 
{
    printf("No error found for this certificate or chain.\n");
}

printf("\nInfo status for the chain:\n");
DWORD infoStatus = pChainContext->TrustStatus.dwInfoStatus;

if((infoStatus & CERT_TRUST_HAS_EXACT_MATCH_ISSUER) != 0)
{
    printf("An exact match issuer certificate has been found for "
         "this certificate.\n");
}
if((infoStatus & CERT_TRUST_HAS_KEY_MATCH_ISSUER) != 0)
{
    printf("A key match issuer certificate has been found for this "
        "certificate.\n");
}
if((infoStatus & CERT_TRUST_HAS_NAME_MATCH_ISSUER) != 0)
{
    printf("A name match issuer certificate has been found for this "
        "certificate.\n");
}
if((infoStatus & CERT_TRUST_IS_SELF_SIGNED) != 0)
{
    printf("This certificate is self-signed.\n");
}
if((infoStatus & CERT_TRUST_IS_COMPLEX_CHAIN) != 0)
{
    printf("The certificate chain created is a complex chain.\n");
}
else // No dwInfoStatus bits set
{
    printf("No information status reported.\n");
}


//-------------------------------------------------------------------
// Duplicate the original chain.
if(pDupContext = CertDuplicateCertificateChain(
       pChainContext ))
{
  printf("Duplicated the chain.\n");
}
else
{
  printf("Duplication failed.\n"); 
}
//-------------------------------------------------------------------
// Free both chains.

CertFreeCertificateChain(pDupContext);
printf("The duplicate chains is free.\n");
CertFreeCertificateChain(pChainContext);
printf("The Original chain is free.\n");
printf("\nPress Enter to continue.");
getchar();
} // end while loop 

printf("\nThere are no more certificates in the store. \n");

//---------------------------------------------------------
// Free the chain engine.

CertFreeCertificateChainEngine(hChainEngine);
printf("The chain engine has been released.\n");

// Free memory for pszNameString.
if(pszNameString)
     free(pszNameString);

printf("The demo program ran to completion without error.\n");


} // end main

//-------------------------------------------------------------------
// This example uses the function MyHandleError, a simple error
// handling function to print an error message and exit 
// the program. 
// For most applications, replace this function with one 
// that does more extensive error reporting.

void MyHandleError(char *s)
{
    fprintf(stderr,"An error occurred in running the program. \n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr, "Error number %x.\n", GetLastError());
    fprintf(stderr, "Program terminating. \n");
    exit(1);
} // end MyHandleError