[xmlsec] Re: GOST support in xmlsec
Dmitry Belyavsky
beldmit at cryptocom.ru
Mon Feb 13 03:09:16 PST 2006
Greetings!
On Fri, 10 Feb 2006, Aleksey Sanin wrote:
> > The patch against CVS (rev 1.8) is attached.
>
> Thanks!!! Now, I applied the patch, did run the unit tests
> and it seems like quite a lot of tests are failing with the
> patch. It seems to me that most of these failures are related
> to the changes in x509vfy.c. Do you think it makes sense
> to separate the gost and x509vfy.c patches?
We've fixed x509vfy.c patch. The problem was in two typos in recursion
calls. New version is attached.
Thank you!
--
SY, Dmitry Belyavsky (ICQ UIN 11116575)
-------------- next part --------------
--- x509vfy.c 2006-02-10 18:43:07.000000000 +0300
+++ xmlsec/src/mscrypto/x509vfy.c 2006-02-13 13:34:22.000000000 +0300
@@ -261,101 +261,118 @@
xmlFree(subject);
}
-static DWORD
-xmlSecBuildChainUsingWinapi (PCCERT_CONTEXT pCertContext, LPFILETIME pfTime,
- HCERTSTORE hAdditionalStore)
+/**
+ @cert: the certificate we check
+ @pfTime: pointer to FILETIME that we are interested in
+ @store_untrusted: untrusted certificates added via API
+ @store_doc: untrusted certificates/CRLs extracted from a document
+ */
+static BOOL
+xmlSecBuildChainUsingWinapi (PCCERT_CONTEXT cert, LPFILETIME pfTime,
+ HCERTSTORE store_untrusted, HCERTSTORE store_doc)
{
- PCCERT_CHAIN_CONTEXT pChainContext;
- CERT_ENHKEY_USAGE EnhkeyUsage;
- CERT_USAGE_MATCH CertUsage;
- CERT_CHAIN_PARA ChainPara;
- DWORD dwFlags=CERT_CHAIN_REVOCATION_CHECK_CHAIN;
- DWORD dwRes = 0;
+ PCCERT_CHAIN_CONTEXT pChainContext = NULL;
+ CERT_CHAIN_PARA chainPara;
+ BOOL rc = FALSE;
+ HCERTSTORE store_add = NULL;
/* Initialize data structures. */
- EnhkeyUsage.cUsageIdentifier = 0;
- EnhkeyUsage.rgpszUsageIdentifier=NULL;
- CertUsage.dwType = USAGE_MATCH_TYPE_AND;
- CertUsage.Usage = EnhkeyUsage;
- ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
- ChainPara.RequestedUsage=CertUsage;
+ memset(&chainPara, 0, sizeof(CERT_CHAIN_PARA));
+ chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
+
+ /* Create additional store for CertGetCertificateChain() */
+ store_add = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 0, NULL);
+ if (!store_add) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "chain additional collection store",
+ "CertOpenStore",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
+ if (!CertAddStoreToCollection(store_add, store_doc, 0, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "adding document store",
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
+ if (!CertAddStoreToCollection(store_add, store_untrusted, 0, 0)) {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "adding untrusted store",
+ "CertAddStoreToCollection",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
/* Build a chain using CertGetCertificateChain
and the certificate retrieved. */
-
if(!CertGetCertificateChain(
NULL, /* use the default chain engine */
- pCertContext,
+ cert,
pfTime,
- hAdditionalStore,
- &ChainPara, /* use AND logic and enhanced key usage
- as indicated in the ChainPara
- data structure */
- dwFlags,
+ store_add,
+ &chainPara,
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN,
NULL,
&pChainContext))
{
xmlSecError(XMLSEC_ERRORS_HERE,
+ "building certificate chain, checking root",
+ "CertGetCertificateChain",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ goto end;
+ }
+ if (pChainContext->TrustStatus.dwErrorStatus == CERT_TRUST_REVOCATION_STATUS_UNKNOWN) {
+ CertFreeCertificateChain(pChainContext); pChainContext = NULL;
+ if(!CertGetCertificateChain(
+ NULL, /* use the default chain engine */
+ cert,
+ pfTime,
+ store_add,
+ &chainPara,
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
NULL,
- NULL,
- XMLSEC_ERRORS_R_MALLOC_FAILED,
+ &pChainContext))
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ "building certificate chain, excluding root",
+ "CertGetCertificateChain",
+ XMLSEC_ERRORS_R_CRYPTO_FAILED,
XMLSEC_ERRORS_NO_MESSAGE);
- return (-1);
+ goto end;
+ }
}
- dwRes = pChainContext->TrustStatus.dwErrorStatus;
+ if (pChainContext->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
+ rc = TRUE;
- CertFreeCertificateChain(pChainContext);
- return (dwRes);
+end:
+ if (pChainContext) CertFreeCertificateChain(pChainContext);
+ if (store_add) CertCloseStore(store_add, 0);
+ return (rc);
}
-
+/**
+ @cert: the certificate we check
+ @pfTime: pointer to FILETIME that we are interested in
+ @store_trusted: trusted certificates added via API
+ @store_untrusted: untrusted certificates added via API
+ @certs: untrusted certificates/CRLs extracted from a document
+ @store: pointer to store klass passed to error functions
+ */
static BOOL
-xmlSecMSCryptoX509StoreConstructCertsChain(xmlSecKeyDataStorePtr store, PCCERT_CONTEXT cert, HCERTSTORE certs,
- xmlSecKeyInfoCtx* keyInfoCtx) {
- xmlSecMSCryptoX509StoreCtxPtr ctx;
+xmlSecMSCryptoBuildCertChainManually (PCCERT_CONTEXT cert, LPFILETIME pfTime,
+ HCERTSTORE store_trusted, HCERTSTORE store_untrusted, HCERTSTORE certs,
+ xmlSecKeyDataStorePtr store) {
PCCERT_CONTEXT issuerCert = NULL;
- FILETIME fTime;
DWORD flags;
- DWORD dwApiCheckResult;
-
- xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), FALSE);
- xmlSecAssert2(cert != NULL, FALSE);
- xmlSecAssert2(cert->pCertInfo != NULL, FALSE);
- xmlSecAssert2(certs != NULL, FALSE);
- xmlSecAssert2(keyInfoCtx != NULL, FALSE);
-
- ctx = xmlSecMSCryptoX509StoreGetCtx(store);
- xmlSecAssert2(ctx != NULL, FALSE);
- xmlSecAssert2(ctx->trusted != NULL, FALSE);
- xmlSecAssert2(ctx->untrusted != NULL, FALSE);
-
- if(keyInfoCtx->certsVerificationTime > 0) {
- /* convert the time to FILETIME */
- xmlSecMSCryptoUnixTimeToFileTime(keyInfoCtx->certsVerificationTime, &fTime);
- } else {
- /* Defaults to current time */
- GetSystemTimeAsFileTime(&fTime);
- }
- dwApiCheckResult = xmlSecBuildChainUsingWinapi(cert, &fTime, ctx->trusted);
-
- switch(dwApiCheckResult)
- {
- case CERT_TRUST_NO_ERROR :
- return (TRUE);
- case CERT_TRUST_IS_NOT_TIME_VALID:
- case CERT_TRUST_IS_NOT_TIME_NESTED:
- case CERT_TRUST_IS_REVOKED:
- case CERT_TRUST_IS_NOT_SIGNATURE_VALID:
- return (FALSE);
- default:
- /* Other errors may be fixed by in-document certificates */
- break;
- }
-
- if (!xmlSecMSCrypoVerifyCertTime(cert, &fTime)) {
+ if (!xmlSecMSCrypoVerifyCertTime(cert, pfTime)) {
xmlSecMSCryptoX509StoreCertError(store, cert, CERT_STORE_TIME_VALIDITY_FLAG);
return(FALSE);
}
@@ -363,11 +380,12 @@
if (!xmlSecMSCryptoCheckRevocation(certs, cert)) {
return(FALSE);
}
+
/**
* Try to find the cert in the trusted cert store. We will trust
* the certificate in the trusted store.
*/
- issuerCert = CertFindCertificateInStore(ctx->trusted,
+ issuerCert = CertFindCertificateInStore(store_trusted,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_NAME,
@@ -375,6 +393,8 @@
NULL);
if( issuerCert != NULL) {
/* We have found the trusted cert, so return true */
+ /* todo: do we want to verify the trusted cert's revocation? we must,
+ * I think */
CertFreeCertificateContext( issuerCert ) ;
return( TRUE ) ;
}
@@ -385,7 +405,7 @@
}
/* try to find issuer cert in the trusted cert in the store */
- issuerCert = CertFindCertificateInStore(ctx->trusted,
+ issuerCert = CertFindCertificateInStore(store_trusted,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_NAME,
@@ -398,7 +418,8 @@
CertFreeCertificateContext(issuerCert);
return(FALSE);
}
- /* todo: do we want to verify the trusted cert? */
+ /* todo: do we want to verify the trusted cert? we must check
+ * revocation, I think */
CertFreeCertificateContext(issuerCert);
return(TRUE);
}
@@ -417,7 +438,7 @@
CertFreeCertificateContext(issuerCert);
return(FALSE);
}
- if(!xmlSecMSCryptoX509StoreConstructCertsChain(store, issuerCert, certs, keyInfoCtx)) {
+ if(!xmlSecMSCryptoBuildCertChainManually(issuerCert, pfTime, store_trusted, store_untrusted, certs, store)) {
xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
CertFreeCertificateContext(issuerCert);
return(FALSE);
@@ -427,7 +448,7 @@
}
/* try the untrusted certs in the store */
- issuerCert = CertFindCertificateInStore(ctx->untrusted,
+ issuerCert = CertFindCertificateInStore(store_untrusted,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_NAME,
@@ -440,7 +461,7 @@
CertFreeCertificateContext(issuerCert);
return(FALSE);
}
- if(!xmlSecMSCryptoX509StoreConstructCertsChain(store, issuerCert, certs, keyInfoCtx)) {
+ if(!xmlSecMSCryptoBuildCertChainManually(issuerCert, pfTime, store_trusted, store_untrusted, certs, store)) {
CertFreeCertificateContext(issuerCert);
return(FALSE);
}
@@ -451,6 +472,44 @@
return(FALSE);
}
+static BOOL
+xmlSecMSCryptoX509StoreConstructCertsChain(xmlSecKeyDataStorePtr store, PCCERT_CONTEXT cert, HCERTSTORE certs,
+ xmlSecKeyInfoCtx* keyInfoCtx) {
+ xmlSecMSCryptoX509StoreCtxPtr ctx;
+ PCCERT_CONTEXT tempCert = NULL;
+ FILETIME fTime;
+
+ xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), FALSE);
+ xmlSecAssert2(cert != NULL, FALSE);
+ xmlSecAssert2(cert->pCertInfo != NULL, FALSE);
+ xmlSecAssert2(certs != NULL, FALSE);
+ xmlSecAssert2(keyInfoCtx != NULL, FALSE);
+
+ ctx = xmlSecMSCryptoX509StoreGetCtx(store);
+ xmlSecAssert2(ctx != NULL, FALSE);
+ xmlSecAssert2(ctx->trusted != NULL, FALSE);
+ xmlSecAssert2(ctx->untrusted != NULL, FALSE);
+
+ if(keyInfoCtx->certsVerificationTime > 0) {
+ /* convert the time to FILETIME */
+ xmlSecMSCryptoUnixTimeToFileTime(keyInfoCtx->certsVerificationTime, &fTime);
+ } else {
+ /* Defaults to current time */
+ GetSystemTimeAsFileTime(&fTime);
+ }
+
+ tempCert = CertEnumCertificatesInStore(ctx->trusted, NULL);
+ if (tempCert) {
+ /* If ctx->trusted has any certificated, we trust the user for
+ * all the information about certificates... */
+ CertFreeCertificateContext(tempCert);
+ return xmlSecMSCryptoBuildCertChainManually(cert, &fTime, ctx->trusted, ctx->untrusted, certs, store);
+ } else {
+ /* ... otherwise we trust the system for trusted root certificates. */
+ return xmlSecBuildChainUsingWinapi(cert, &fTime, ctx->untrusted, certs);
+ }
+}
+
/**
* xmlSecMSCryptoX509StoreVerify:
* @store: the pointer to X509 certificate context store klass.
More information about the xmlsec
mailing list