EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Validate certificate chain

Also by EldoS: CallbackDisk
Create virtual disks backed by memory or custom location, expose disk images as disks and more.
#22013
Posted: 10/15/2012 15:35:34
by Matthijs Hoekstra (Basic support level)
Joined: 11/10/2011
Posts: 7

Hello,

I am trying to write some code to validate a SSL certificate (including the chain) with every https get call.

The event (OnCertificateValidate)is called fine

CertificateValidator.Validate(X509Certificate, ref Validity, ref Reason);
Validate = (Validity == TSBCertificateValidity.cvOk);

At the moment returns always false (reason 32)

I am loading a SPC file in the certificate store. So my guess is I don't have an SPC file with the entire chain (CA seems to be missing)

So what code do I need to save the chain from for example https://www.microsoft.com/ ? I have the following code:

private void saveCertificate_Click(object sender, RoutedEventArgs e)
{

TElHTTPSClient HTTPSClient = new TElHTTPSClient();
HTTPSClient.OnCertificateValidate += new SBSSLCommon.TSBCertificateValidateEvent(cl_OnCertificateValidate);

int ret = HTTPSClient.Get("https://www.microsoft.com/");

}

void cl_OnCertificateValidate(object Sender, SBX509.TElX509Certificate X509Certificate, ref SBUtils.TSBBoolean Validate)
{

Debug.WriteLine("Certificate owner: " + X509Certificate.SubjectName.CommonName);

//save het certificate zodat we deze later kunnen gebruiken. Te vinden in ISOStorage en met
//http://wptools.codeplex.com uit isostorage gehaald en in het project opgenomen.
string FileName = "microsoft.com_"+ X509Certificate.SubjectName.CommonName+ ".SPC";

int size = X509Certificate.CertificateSize;
byte[] buf;

var result = X509Certificate.SaveToBufferSPC(out buf);


using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(FileName))
{
myIsolatedStorage.DeleteFile(FileName);
}
using (IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream(FileName, FileMode.Create, myIsolatedStorage))
{
using (BinaryWriter writer = new BinaryWriter(fileStream))
{
writer.Write(buf, 0, buf.Count());
}
}
}

Validate = true;

}

This writes 3 files to ISO storage (I am working on a Windows Phone)

I read these files in my store when starting the app with the following code:

Uri uri = new Uri("PhoneApp2;component/microsoft.com.SPC", UriKind.RelativeOrAbsolute);
StreamResourceInfo sri = Application.GetResourceStream(uri);
cert1 = new TElX509Certificate();
cert1.LoadFromStreamSPC(sri.Stream, 0);

Uri uri2 = new Uri("PhoneApp2;component/microsoft.com.SPC", UriKind.RelativeOrAbsolute);
StreamResourceInfo sri2 = Application.GetResourceStream(uri2);
cert2 = new TElX509Certificate();
cert2.LoadFromStreamSPC(sri2.Stream, 0);

Uri uri3 = new Uri("PhoneApp2;component/microsoft.com.SPC", UriKind.RelativeOrAbsolute);
StreamResourceInfo sri3 = Application.GetResourceStream(uri3);
cert3 = new TElX509Certificate();
cert3.LoadFromStreamSPC(sri3.Stream, 0);


store = new TElMemoryCertStorage();
store.Add(cert1, true);
store.Add(cert2, true);
store.Add(cert3, true);



CertificateValidator = new TElX509CertificateValidator();
CertificateValidator.OfflineMode = true;
CertificateValidator.MandatoryCRLCheck = false;
CertificateValidator.MandatoryRevocationCheck = false;
CertificateValidator.MandatoryOCSPCheck = false;

CertificateValidator.CheckCRL = false;
CertificateValidator.CheckOCSP = false;
CertificateValidator.IgnoreCAKeyUsage = true;

CertificateValidator.AddKnownCertificates(store);
CertificateValidator.AddTrustedCertificates(store);

But it still never validates the HTTPS requests I am trying to do.

I am guessing I am missing something really obvious :) any tips?
#22017
Posted: 10/15/2012 18:54:10
by Ken Ivanov (EldoS Corp.)

Matthijs,

Thank you for contacting us.

Normally you shouldn't extract certificates from a chain manually before passing them for validation. The validator picks the whole chain automatically from the end-entity certificate's Chain property, so all the certificates provided by the server within an SSL handshake get known to the validator without any user intervention. Still, I suspect there is a copy-paste issue in your code (uri1, uri2 and uri3 access the same certificate file).

Validation reason of 32 stands for vrUnknownCA reason. This reason is returned if the validator couldn't build one or more chains involved in the validation. As microsoft.com returns a complete chain of certificates ending with the root one, the problem is likely to happen with a CRL or OCSP service certificate. You can find out what exactly certificate the validator fails to find by handling the OnCACertificateNeeded event and checking the issuer of the passed Certificate parameter.
#22024
Posted: 10/15/2012 23:59:54
by Matthijs Hoekstra (Basic support level)
Joined: 11/10/2011
Posts: 7

Thanks, I fixed the typos.

In short what I try to do is to validate the entire chain of a non public certificate chain. I want to proof it by using the Microsoft.com sample.

What code do I need to write to store the entire chain into a PCS file? I know wrote a little code which saves the PCS files. When trying this with the Microsoft.com server I get back 3 files. But none are the CA? (Can I disable the CA check? (the app does fire the OnCACertificateNeeded event.
#22025
Posted: 10/16/2012 00:23:12
by Eugene Mayevski (EldoS Corp.)

What you need to do to properly capture server certificates is:

1) Create an instance of TElMemoryCertStorage
2) In OnCertificateValidate event handler add the received certificate to the instance of TElMemoryCertStorage
3) when all certificates are received, use one of TElMemoryCertStorage.SaveTo*() methods to save everything to the file. SaveToStream would save certificates to PKCS#7.

Now, when you connect to the server, it sends some certificate, but not all. *At least* there's no root CA there, and intermediate CA can be also missing. It's supposed that you have a list of trusted ROOT CAs on your system and some webmasters (for a reason or not) suppose that intermediate certificate is also on your system.

With Windows Phone things become complicated as there's no accessible Windows Certificate Storage there. Consequently you need to carry trusted certificates with you.

The easiest you can do is capture all certificates of windows by using TElWinCertStorage. Remember to choose one store per iteration using SystemStores property and then save certificates using TElWinCertStorage.SaveToStream() method. So you would capture ROOT and CA stores separately. Then you can carry your stores with you.

Additionally SecureBlackbox 10 contains CertificateRetriever mechanism that automatically downloads CA certificate if its location is specified in the certificate being validated.


Sincerely yours
Eugene Mayevski

Reply

Statistics

Topic viewed 1779 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!