[xmlsec] Re: GOST support in xmlsec

Dmitry Belyavsky beldmit at cryptocom.ru
Fri Feb 10 07:50:50 PST 2006


Greetings!

On Fri, 10 Feb 2006, Aleksey Sanin wrote:

> > Thank you. If you like the patch, I want to discuss the support of GOST
> > Symmetric Encryption.
>
> I like the patch and it looks pretty straightforwad to me except one
> change in src/mscrypto/x509vfy.c Probably the biggest problem I have is
> that the patch does not want to apply correctly on the current TRUNK
> (you mentioned that you did diff against 1.2.9). Can you explain what is
> going on there? And if you can produce a patch against current trunk
> I will greatly appreciate it.

The patch against CVS (rev 1.8) is attached. It contains some fixes to the
xmlSecBuildChainUsingWinapi function for better usage of system storage.

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-09 11:53:19.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(cert, 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(cert, 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