Certificati, Store e un po' di utilities via CryptoAPI
Oggi ho dovuto riesumare i ricordi sulle CryptoAPI e C SDK. Ecco un po' di codice per la gestione dei certificati X509, i certificate store, i key containers e un po' di utilities che possono risultare utili :-)
Attenzione, se riutilizzate il codice verificate che si integri con il vostro sistema di Exception Management!!
Certificati
/**************************************************************************
* Function: void CSpy_DumpExtraCertInfo(PCCERT_CONTEXT pcert)
*
* Purpose : Print additional Certificate information
**************************************************************************/
void CSpy_DumpExtraCertInfo(PCCERT_CONTEXT pcert)
{
TCHAR szName[1000];
PCCERT_CONTEXT pCurrentCert;
PCCERT_CONTEXT pIssuerCert;
DWORD dwVerificationFlags;
LPWSTR lpszString = (LPWSTR)malloc(sizeof(TCHAR) * MAX_PATH);
SYSTEMTIME stNotBefore,stNotAfter;
DWORD dwBitLen;
DWORD dwData;
PBYTE pThumbprint;
PBYTE pData;
__try{
_tprintf(L"\n");
// display leaf name
if(!CertNameToStr(pcert->dwCertEncodingType,
&pcert->pCertInfo->Subject,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, (DWORD)sizeof(TCHAR)*(_tcslen(szName)+1)))
{
_tprintf(L"**** Error 0x%x building subject name\n", GetLastError());
}
_tprintf(L" subject: %s\n", szName);
if(!CertNameToStr(pcert->dwCertEncodingType,
&pcert->pCertInfo->Issuer,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, (DWORD)sizeof(TCHAR)*(_tcslen(szName)+1)))
{
_tprintf(L"**** Error 0x%x building issuer name\n", GetLastError());
}
_tprintf(L" issuer: %s\n", szName);
_tprintf(L" serial number: ");
dwData = pcert->pCertInfo->SerialNumber.cbData;
for (DWORD n = 0; n < dwData; n++)
{
_tprintf(L"%02X",pcert->pCertInfo->SerialNumber.pbData[dwData - (n + 1)]);
if( n>0&&(1== n % 2))
_tprintf(L" ");
}
_tprintf(L"\n");
FileTimeToSystemTime(&pcert->pCertInfo->NotBefore, &stNotBefore);
wsprintf(lpszString, L"%02d/%02d/%d",stNotBefore.wDay, stNotBefore.wMonth, stNotBefore.wYear);
_tprintf(L" NotBefore : %s\n",lpszString);
FileTimeToSystemTime(&pcert->pCertInfo->NotAfter, &stNotAfter);
wsprintf(lpszString, L"%02d/%02d/%d",stNotAfter.wDay, stNotAfter.wMonth, stNotAfter.wYear);
_tprintf(L" NotAfter : %s\n",lpszString);
//Thumbprint
_tprintf(L" Thumbprint : ");
if (!CertGetCertificateContextProperty(pcert,
CERT_SHA1_HASH_PROP_ID,
NULL,
&dwData))
{
_tprintf(L"Error : CertGetCertificateContextProperty() failed in retrieve memory settings.\n");
return;
}
if (NULL == (pThumbprint = (BYTE*) malloc(dwData)))
{
_tprintf(L"Error [E_OUTOFMEMORY]: malloc() failed.\n");
return;
}
if (!CertGetCertificateContextProperty(pcert,
CERT_SHA1_HASH_PROP_ID,
pThumbprint,
&dwData))
{
_tprintf(L"Error : CertGetCertificateContextProperty() failed.\n");
return;
}
for (DWORD n = 0; n < dwData; n++)
{
_tprintf(L"%02X",pThumbprint[n]);
if( n>0&&(1== n % 2))
_tprintf(L" ");
}
_tprintf(L"\n");
free(pThumbprint);
//UI description
if(CertGetCertificateContextProperty(pcert,
CERT_DESCRIPTION_PROP_ID,
NULL,
&dwData))
{
if (NULL == (pData = (BYTE*) malloc(dwData)))
{
_tprintf(L"Error [E_OUTOFMEMORY]: malloc() failed.\n");
return;
}
if(CertGetCertificateContextProperty(pcert,
CERT_DESCRIPTION_PROP_ID,
pData,
&dwData))
{
_tprintf(L" Description=%s\n",pData);
}
free(pData);
} //end od UI
CSpy_DumpCertificateExtensions(pcert);
//Public Key Infos
_tprintf(L" Public Key :\n");
if (0 != (dwBitLen = CertGetPublicKeyLength(
MY_ENCODING_TYPE,
&pcert->pCertInfo->SubjectPublicKeyInfo)))
_tprintf(L" length=%i\n", dwBitLen);
else
_tprintf(L"**** Error 0x%x in CertGetPublicKeyLength\n", GetLastError());
_tprintf(L" Algorithm ID= ");
//TODO: Add a new function to decode CRYPT_ALGORITHM_IDENTIFIER
int counter=0;
while(pcert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId[counter] != '\0')
{
_tprintf(L"%c",pcert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId[counter++]);
}
_tprintf(L"\n");
_tprintf(L" Key=");
dwData = pcert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData;
for (DWORD n = 0; n < dwData; n++)
{
_tprintf(L"%02X",pcert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData[n]);
if( n>0&&(1== n % 2))
_tprintf(L" ");
}
_tprintf(L"\n");
//_tprintf(L" Private Key : %s",(CSpy_CertificateHasPrivateKey(pcert))?L"Present":L"Not present");
_tprintf(L" Private Key : ");
if(CSpy_CertificateHasPrivateKey(pcert))
{
_tprintf(L"YES\n");
CSpy_DumpCSPInfos(pcert);
}else
{
_tprintf(L"NO\n");
}
// display certificate chain
pCurrentCert = pcert;
while(pCurrentCert != NULL)
{
dwVerificationFlags = 0;
pIssuerCert = CertGetIssuerCertificateFromStore(pcert->hCertStore,
pCurrentCert,
NULL,
&dwVerificationFlags);
if(pIssuerCert == NULL)
{
if(pCurrentCert != pcert)
{
CertFreeCertificateContext(pCurrentCert);
}
break;
}
if(!CertNameToStr(pIssuerCert->dwCertEncodingType,
&pIssuerCert->pCertInfo->Subject,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, (DWORD)sizeof(TCHAR)*(_tcslen(szName)+1)))
{
_tprintf(L"**** Error 0x%x building subject name\n", GetLastError());
}
_tprintf(L" CA subject: %s\n", szName);
if(!CertNameToStr(pIssuerCert->dwCertEncodingType,
&pIssuerCert->pCertInfo->Issuer,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
szName, (DWORD)sizeof(TCHAR)*(_tcslen(szName)+1)))
{
_tprintf(L"**** Error 0x%x building issuer name\n", GetLastError());
}
_tprintf(L" CA issuer: %s\n\n", szName);
if(pCurrentCert != pcert)
{
CertFreeCertificateContext(pCurrentCert);
}
pCurrentCert = pIssuerCert;
pIssuerCert = NULL;
}
} //end__try
__finally
{
}
}
/**************************************************************************
* Function: bool CSpy_CertificateHasPrivateKey(PCCERT_CONTEXT pcert)
*
* Purpose : Test if a certificate has the private key
**************************************************************************/
bool CSpy_CertificateHasPrivateKey(PCCERT_CONTEXT pcert)
{
DWORD cb = 0;
return CertGetCertificateContextProperty(pcert,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&cb)
!=0; //to avoid Compiler warning (level 3) C4800
}
/**************************************************************************
* Function: UINT CSpy_DumpCertificateExtensions(PCCERT_CONTEXT pCertContext)
*
* Purpose : Display cert extensions. Return number of extensions
**************************************************************************/
UINT CSpy_DumpCertificateExtensions(PCCERT_CONTEXT pCertContext)
{
_tprintf(L" N. Ext. : %d\n",pCertContext->pCertInfo->cExtension);
if (pCertContext->pCertInfo->cExtension>0)
{
for(int x =0; x <(int)pCertContext->pCertInfo->cExtension;x++)
{
_tprintf(L" Critical=%s ",(pCertContext->pCertInfo->rgExtension->fCritical)? L"Yes":L"NO");
_tprintf(L" OID=");
int n=0;
while(pCertContext->pCertInfo->rgExtension->pszObjId[n]!='\0')
_tprintf(L"%c",(TCHAR)pCertContext->pCertInfo->rgExtension->pszObjId[n++]);
_tprintf(L"\n");
pCertContext->pCertInfo->rgExtension++;
}//endfor(int x =0; x <pCertContext->pCertInfo->cExtension;x++)
} //endif (pCertContext->pCertInfo->cExtension>0)
return pCertContext->pCertInfo->cExtension;
}
Certificate Store
/**************************************************************************
* Function: void CSpy_DumpStore(TCHAR *storeName)
*
* Purpose : Open a list all certificate in a store
**************************************************************************/
void CSpy_DumpStore(TCHAR *storeName)
{
HCERTSTORE hCertStore;
PCCERT_CONTEXT pCertContext = NULL;
DWORD dwFlags=0;
DWORD dwStrType = CERT_OID_NAME_STR;
DWORD cbNameLen;
TCHAR *sz;
long nCerts=0;
if (_tcsclen(storeName) > MAX_PATH )
storeName[MAX_PATH] = '\0';
_tprintf(L"\nDumping '%s' Store.....\n",storeName);
//--------------------------------------------------------------------
// Begin Processing by opening a certificate store.
if(!(hCertStore=CertOpenStore(
CERT_STORE_PROV_SYSTEM,
MY_ENCODING_TYPE,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER|CERT_STORE_OPEN_EXISTING_FLAG ,
storeName)))
{
CSpy_DisplayError(L"The store did not open.");
}
while(pCertContext = CertEnumCertificatesInStore(
hCertStore,
pCertContext))
{
//--------------------------------------------------------------------
// Get and display
// the name of subject of the certificate.
if(!(cbNameLen = CertGetNameString(pCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,NULL,0)))
{
CSpy_DisplayError(L"CertGetName 1 failed.");
}
if(!(sz = (TCHAR*) malloc(sizeof(TCHAR) *cbNameLen+1)))
CSpy_DisplayError(L"Memory allocation failed.");
if(CertGetNameString(pCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,(LPWSTR)sz,cbNameLen+1))
{
_tprintf(L"\nCertificate n. %d Version=V%d :(%s).",nCerts+1,pCertContext->pCertInfo->dwVersion+1,sz);
}
else
{
CSpy_DisplayError(L"CertGetName failed.");
}
free(sz);
CSpy_DumpExtraCertInfo(pCertContext);
nCerts++;
} // End of while loop
_tprintf(L"\n=>Total : %s store contains %d certificates",storeName,nCerts);
//--------------------------------------------------------------------
// Close the store.
if(CertCloseStore(hCertStore,CERT_CLOSE_STORE_CHECK_FLAG))
{
if(true == g_bverbose)
_tprintf(L"The store is closed. All certificates are released.\n");
}
else
{
if(true == g_bverbose)
_tprintf(L"The store was closed, but certificates still in use.\n");
}
}
Key Containers
/**************************************************************************
* Function: DWORD CSpy_DeleteKeyContainer(PCCERT_CONTEXT pCertContext)
*
* Purpose :
**************************************************************************/
DWORD CSpy_DeleteKeyContainer(PCCERT_CONTEXT pCertContext)
{
DWORD nRetCode = 0;
DWORD cb = 0;
CRYPT_KEY_PROV_INFO * pKeyProvInfo = NULL;
__try
{
HCRYPTPROV hCryptProv;
if (!CryptAcquireContext(&hCryptProv,
pKeyProvInfo->pwszContainerName,
pKeyProvInfo->pwszProvName,
pKeyProvInfo->dwProvType,
CRYPT_DELETEKEYSET))
{
CSpy_DisplayError (L"Unable to Delete the context.");
_tprintf(L" %s ",pKeyProvInfo->pwszContainerName);
__leave;
}
}
__finally
{
if (pKeyProvInfo)
{
free(pKeyProvInfo);
}
}
return nRetCode;
}
Utilities
/**************************************************************************
* Function: VOID DumpBinaryData( PBYTE pBuffer, ULONG uLen )
*
* Purpose : DumpBinaryData()
**************************************************************************/
VOID CSpy_DumpBinaryData( PBYTE pBuffer, ULONG uLen )
{
TCHAR *p = (TCHAR *)pBuffer;
TCHAR c;
DWORD dw;
UINT i = 0;
_tprintf(L"{\n ");
while( i < uLen ) {
c = *p;
dw = (DWORD)(c);
_tprintf(L"0x%02X, ", dw & 0xFF );
i++;
p++;
if ((i % 8) == 0)
_tprintf(L"\n " );
}
_tprintf(L"\n}\n" );
}
--Mario
Comments
- Anonymous
February 05, 2008
PingBack from http://www.biosensorab.org/2008/02/06/certificati-store-e-un-po-di-utilities-via-cryptoapi/