Exemple de programme C : création d’une chaîne de certificats
L’exemple suivant crée et installe un moteur de chaîne de certificats non défini par défaut. Le moteur est utilisé pour générer des chaînes de certificats pour chacun des certificats dans un magasin de certificats.
Cet exemple illustre les tâches et fonctions CryptoAPI suivantes :
- Préparation à la création d’un moteur de chaîne de certificats non défini par défaut en déclarant et initialisant une structure de données CERT_CHAIN_ENGINE_CONFIG .
- Création du moteur de recherche à l’aide de CertCreateCertificateChainEngine.
- Utilisation de CertOpenSystemStore pour ouvrir le magasin Mon système.
- Récupération de tous les certificats du magasin ouvert à l’aide de CertEnumCertificatesInStore dans une boucle.
- Pour chaque certificat dans le magasin ouvert, récupérez le nom de l’objet à partir du certificat à l’aide de CertGetNameString.
- Génération d’une chaîne de certificats pour chaque certificat à l’aide de CertGetCertificateChain.
- Création d’un doublon de la chaîne de certificats à l’aide de CertDuplicateCertificateChain.
- Utilisation de CertFreeCertificateChain pour libérer chaque chaîne avant la génération de la chaîne suivante.
#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