When I inspect the files with SignTool the certificates are present, but the
CertEnumCertificatesInStore does not always return all of the certificates.
Code fragment below
list <CertificateInfo *>getSigningCertsFromStore2(HCERTSTORE store) {
PCCERT_CONTEXT currContext = NULL;
list < CertificateInfo * >ret;
while( currContext = CertEnumCertificatesInStore( store, currContext ) ) {
if( currContext != NULL ) {
CertificateInfo *cert = new CertificateInfo(
currContext->pbCertEncoded, currContext->cbCertEncoded );
if( isSigningBased(currContext) ) {
ret.push_back( cert );
} else {
// TO verify that we didn't reject the root cert.
printf("Rejected Cert, Subject=%s\n",
cert->getSubject().c_str());
}
}
} while( currContext != NULL );
ret = orderCerts(ret);
return ret;
}
list < CertificateInfo * >getEmbeddedCertificateFromFile( const char
*filepath )
{
HCERTSTORE store = NULL;
HCRYPTMSG msg = NULL;
DWORD encoding,
content,
format;
list < CertificateInfo * >ret;
WCHAR wideFilePath[MAX_PATH];
MultiByteToWideChar( CP_ACP, 0, filepath, -1, wideFilePath, MAX_PATH );
if ( CryptQueryObject( CERT_QUERY_OBJECT_FILE,
wideFilePath,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0,
&encoding,
&content,
&format,
&store,
&msg,
NULL ) != 0 ) {
ret = getSigningCertsFromStore2(store);
}
if( store != NULL ) {
CertCloseStore( store, 0);
}
if ( msg != NULL ) {
CryptMsgClose( msg );
}
return ret;
}
list <certificateinfo*> pList = new list <>
and return this.
Also you can simplifly your code:
a) You don't need "if( currContext != NULL )" since you won't enter the
first "while loop" unless the above condition is true.
b) You don't need the second while loop. Remove it.
Other than the above, I don't see anything wrong with the code in the "while
loop" except I don't know what orderCerts is doing. It's highly UNLIKELY that
CertEnumCertificateStore is not returning your cert. Remember that it is a
highly tested method.
Also put a print statement as soon as you got a certificate from the Store,
it should be as follows:
while( currContext = CertEnumCertificatesInStore( store, currContext ) ) {
print the subject name, serial number of the ceritificate
...
}
And make sure it is returning it.
Hope this helps.
The fundamental problem is that CertEnumCertificatesInStore is not returning
all of the certs. If I single step within the debugger it only returns 2 out
of 3 of the certificates that the Properties in the file explorer. I can use
other methods such as the following code, and it too only returns 2 of the 3
certificates. Is there some sort of initialization or other steps prior to
these calls that need to be executed?
list <CertificateInfo *>getSigningCertsFromStore(HCERTSTORE store) {
PCCERT_CONTEXT currContext = NULL;
CERT_ENHKEY_USAGE usage;
list < CertificateInfo * >ret;
memset(&usage, 0, sizeof(usage));
usage.cUsageIdentifier = 1;
usage.rgpszUsageIdentifier = new char *[1];
usage.rgpszUsageIdentifier[0] = szOID_PKIX_KP_CODE_SIGNING;
do {
currContext = CertFindCertificateInStore( store, X509_ASN_ENCODING |
PKCS_7_ASN_ENCODING , 0, CERT_FIND_ANY, &usage, currContext);
if( currContext != NULL ) {
if( isSigningBased(currContext) ) {
CertificateInfo *cert = new CertificateInfo(
currContext->pbCertEncoded, currContext->cbCertEncoded );
ret.push_back( cert );
}
CertFreeCertificateContext( currContext );
}
} while( currContext != NULL );
delete usage.rgpszUsageIdentifier;
return ret;
From MSDN "A non-NULLCERT_CONTEXT that CertFindCertificateInStore returns
must be freed by CertFreeCertificateContext or by being passed as the
pPrevCertContext parameter on a subsequent call to
CertFindCertificateInStore."
It can't be both. Also I am not sure whether you have noticed but when you
say CERT_FIND_ANY the API ignores usage variable.
CERT_FIND_ANY - "Data type of pvFindPara: NULL, not used."