Example C Program: Setting and Getting Certificate Store Properties
The following example sets and gets a certificate store property, the localized store name. This property is not persisted when the store is closed.
This example illustrates the following tasks and CryptoAPI functions:
- Opening a certificate store using CertOpenStore.
- Setting the localized name of the store using CertSetStoreProperty.
- Retrieving the localized name of the store using CertGetStoreProperty.
- Retrieving the predefined localized store name using CryptFindLocalizedName.
- Save the certificate store as a PKCS #7 message to a file using CertSaveStore.
- Save the certificate store to a memory BLOB using CertSaveStore.
- Determine the number of signers of the PKCS #7 message using CryptGetMessageSignercount.
- Open a certificate store from a PKCS #7 message in memory using CryptGetMessageCertificates.
- Initialize the CRYPT_ALGORITHM_IDENTIFIER and CRYPT_HASH_MESSAGE_PARA data structures needed to hash the message
- Hash and encode the message using CryptHashMessage.
- Determine whether changes have been made to an open certificate store and synchronizing the store if needed using CertControlStore.
- Closing a certificate store using CertCloseStore with the CERT_CLOSE_STORE_FORCE_FLAG.
//------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Example C program. // This program demonstrates the use of the following functions: // CreateEvent // CertOpenStore // CertSetStoreProperty // CertGetStoreProperty // CryptFindLocalizedName // CertSaveStore // CryptGetMessageSignerCount // CryptGetMessageCertificates // CryptHashMessage // CertControlStore // WaitForSingleObjectEx // CertCloseStore #pragma comment(lib, "crypt32.lib") #include <stdio.h> #include <windows.h> #include <Wincrypt.h> #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) void MyHandleError(char *s); void main() { //------------------------------------------------------------------- // Declare and initialize variables. HCERTSTORE hCertStore; // Original certificate store HCERTSTORE hNewStore; // Store to be created // from a PKCS #7 message HANDLE hEvent; void *pvData; DWORD cbData; DWORD dwSignerCount; CRYPT_DATA_BLOB Property_Name_Blob; // BLOB to hold store property CRYPT_DATA_BLOB Save_Store_Blob; // BLOB to hold the PKCS #7 // message CRYPT_HASH_MESSAGE_PARA HashPara; // Data structure used // to hash a message const BYTE* rgpbToBeHashed[1]; DWORD rgcbToBeHashed[1]; // Arrays of messages to be // hashed BYTE *pbHashedBlob; DWORD cbHashedBlob; // Length of the hash BLOB CRYPT_ALGORITHM_IDENTIFIER AlgId; // Data structure to hold the // hash algorithm identifier BOOL fSignal; //------------------------------------------------------------------- // Initialize an event. if(hEvent = CreateEvent( NULL, FALSE, // Manual reset is FALSE. FALSE, // The initial state of the event is FALSE. NULL)) { printf("An event has been created.\n"); } else { MyHandleError("The event was not created."); } //------------------------------------------------------------------- // Open the MY certificate store. if ( hCertStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY")) { printf("The MY store is open.\n"); } else { MyHandleError("The MY store did not open."); } //------------------------------------------------------------------- // Prepare a data structure to set a store property. // Initialize the members of the CRYPT_DATA_BLOB. Property_Name_Blob.pbData =(BYTE *) L"The Local MY Store"; Property_Name_Blob.cbData = (wcslen((LPWSTR)Property_Name_Blob.pbData)+1) * sizeof(WCHAR); //------------------------------------------------------------------- // Set the store's localized name property. if (CertSetStoreProperty( hCertStore, CERT_STORE_LOCALIZED_NAME_PROP_ID, 0, &Property_Name_Blob)) { printf("The name of the store has been set. Continue. \n"); } else { MyHandleError("Setting the store's localized name failed."); } //------------------------------------------------------------------- // Call CertGetStoreProperty a first time // to get the length of the store name string to be returned. if(CertGetStoreProperty( hCertStore, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL, // NULL on the first call // to establish the length of the string to // to be returned &cbData)) { printf("The length of the property is %d. \n",cbData); } else { MyHandleError("The length of the property was not calculated."); } //------------------------------------------------------------------- // cbData is the length of a string to be allocated. // Allocate the space for the string, and call the function a // the second time. if(pvData = malloc(cbData)) { printf("%d bytes of memory allocated.\n",cbData); } else { MyHandleError("Memory was not allocated."); } if(CertGetStoreProperty( hCertStore, CERT_STORE_LOCALIZED_NAME_PROP_ID, pvData, &cbData)) { printf("The localized name is %S.\n",pvData); } else { MyHandleError("CertGetStoreProperty failed."); } //------------------------------------------------------------------- // Find and print the predefined localized name for the MY store. // Note that changing the localized store name property does not // change the predefined localized store name. printf("The predefined localized name of the MY " "store is still %S.\n", CryptFindLocalizedName(L"my")); //------------------------------------------------------------------- // Save the store to a PKCS #7 message in a file. if(CertSaveStore( hCertStore, MY_ENCODING_TYPE, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_FILENAME_A, "pkcsseven.dat", 0)) { printf("The store has been saved to a PKCS #7 message file.\n"); } else { MyHandleError("The store has not been saved."); } //------------------------------------------------------------------- // Save the store to a PKCS #7 message in a file. // Initialize the BLOB. Save_Store_Blob.cbData=0; Save_Store_Blob.pbData=NULL; if(CertSaveStore( hCertStore, MY_ENCODING_TYPE, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_MEMORY, (void *)&Save_Store_Blob, 0)) { printf("The store length, %d, has been determined.\n", Save_Store_Blob.cbData); } else { MyHandleError("The store length could not be determined."); } if(Save_Store_Blob.pbData=(BYTE *) malloc(Save_Store_Blob.cbData)) { printf("Memory has been allocated.\n"); } else { MyHandleError("Memory allocation failure."); } if(CertSaveStore( hCertStore, MY_ENCODING_TYPE, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_MEMORY, (void *)&Save_Store_Blob, 0)) { printf("The store has been saved to memory.\n"); } else { MyHandleError("The store was not saved to memory."); } //------------------------------------------------------------------- // Retrieve the number of signers of the PKCS #7 message. if ( dwSignerCount = CryptGetMessageSignerCount( MY_ENCODING_TYPE, Save_Store_Blob.pbData, Save_Store_Blob.cbData)) { printf("The number of signers is %d.\n",dwSignerCount); } else { printf("The number of signers is zero or could not" "be found.\n"); } //------------------------------------------------------------------- // Open a certificate store from the PKCS #7 message stored to // memory. if(hNewStore=CryptGetMessageCertificates( MY_ENCODING_TYPE, NULL, 0, Save_Store_Blob.pbData, Save_Store_Blob.cbData)) { printf("A new store has been opened from a PKCS #7.\n"); } else { MyHandleError("Opening the store from the PKCS #7 " "message failed."); } //------------------------------------------------------------------- // Next, hash the message. // Store the message and its length in the appropriate arrays. rgpbToBeHashed[0]=Save_Store_Blob.pbData; rgcbToBeHashed[0]=Save_Store_Blob.cbData; //------------------------------------------------------------------- // Initialize the CRYPT_ALGORITHM_IDENTIFIER data structure. AlgId.pszObjId=szOID_RSA_MD5; AlgId.Parameters.cbData=0; //------------------------------------------------------------------- // Initialize the CRYPT_HASH_MESSAGE_PARA data structure. HashPara.cbSize = sizeof(CRYPT_HASH_MESSAGE_PARA); HashPara.dwMsgEncodingType=MY_ENCODING_TYPE; HashPara.hCryptProv=NULL; HashPara.HashAlgorithm=AlgId; HashPara.pvHashAuxInfo= NULL; //------------------------------------------------------------------- // Calculate the size of the hashed and encoded message. if(CryptHashMessage( &HashPara, FALSE, 1, rgpbToBeHashed, rgcbToBeHashed, NULL, &cbHashedBlob, NULL, NULL)) { printf("The size of the hashed, encoded message is %d.\n", cbHashedBlob); } else { MyHandleError("The size of the hash could not be determined."); } //------------------------------------------------------------------- // Allocated memory for the hashed, encoded BLOB. if(pbHashedBlob = (BYTE*)malloc(cbHashedBlob)) { printf("Memory allocated for the hashed, encoded BLOB.\n"); } else { MyHandleError("Memory allocation failed."); }; //------------------------------------------------------------------- // Hash and encode the message. if(CryptHashMessage( &HashPara, FALSE, 1, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, &cbHashedBlob, NULL, NULL)) { printf("The message has been hashed and encoded.\n"); } else { MyHandleError("The message was not hashed. "); } //------------------------------------------------------------------- // Call CertControlStore the first time with // CERT_CONTROL_STORE_NOTIFY_CHANGE. if(CertControlStore( hCertStore, // The store to be controlled 0, // Not used CERT_STORE_CTRL_NOTIFY_CHANGE, // Control action type &hEvent)) // Points to the event handle. // When a change is detected, // a signal is written to the // space pointed to by // hHandle. { printf("Notify change worked \n"); } else { MyHandleError("Notify change failed. \n"); } //------------------------------------------------------------------- // Wait for the store to change. fSignal =(WAIT_OBJECT_0 == WaitForSingleObjectEx( hEvent, 1000 , // Number of milliseconds to wait. // Use INFINITE to wait indefinitely for // a change. FALSE)); if (fSignal) //------------------------------------------------------------------- // The store has changed. // Call the function a second time with CERT_STORE_CTRL_RESYNC. if(CertControlStore( hCertStore, // in, the store to be controlled 0, // in, not used. CERT_STORE_CTRL_RESYNC, // in, control action type &hEvent)) // in, the handle of the event // to be rearmed. printf("Resynchronization worked. \n"); else MyHandleError("Resynchronization failed."); else { printf("The store was not changed. \n"); printf("Resynchronization was not needed. \n"); } // Free memory. free (pbHashedBlob); if(pvData) free(pvData); if(CertCloseStore( hCertStore, CERT_CLOSE_STORE_FORCE_FLAG)) { printf("The store has been closed. \n"); } else { MyHandleError("The store could not be closed."); } printf("The 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 to // the standard error (stderr) file 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 of MyHandleError
Show: