EldoS | Feel safer!

Software components for data protection, secure storage and transfer

ValidateForSSL using a CA signed certificate

Also by EldoS: Solid File System
A virtual file system that offers a feature-rich storage for application documents and data with built-in compression and encryption.
#15486
Posted: 01/13/2011 03:21:46
by Vsevolod Ievgiienko (EldoS Corp.)

Quote

So is the process to only try and validate if there is a CACertificate?
and otherwise return Valid?

For OCSP validation the answer is yes.
Quote

Otherwise how can you validate those without a CA? is there another method instead of PerformRequest that will allow you to validate without a CACert?

OCSP works only if CA certificate is avaliable. For certificates that does not have corresponding CA certificate you can disable ElX509CertificateValidator.CheckOCSP and use just ValidateForSSL.
#15499
Posted: 01/13/2011 13:50:38
by Eugene Mayevski (EldoS Corp.)

In fact if you don't have a CA certificate, you are in trouble: you have no way to check validity of the signature of the certificate in question. You can explicitly trust this certificate, but then there's no need to validate it (and search for OCSP etc)


Sincerely yours
Eugene Mayevski
#15525
Posted: 01/17/2011 07:08:13
by Sam Barber (Basic support level)
Joined: 01/11/2011
Posts: 7

Thanks for your help guys,

I'm slightly confused as to what I actually have to do.
So at the moment I have one CA cert on the server, when I receive the certificate chain I can only validate the server certificate not the CA cert itself using the OCSPClient.PerformRequest method because the CA cert does not have it's own CA cert to use in validation.

Running through this it seems as if ValidateForSSL when validating the CA certificate returns a reason of 32 - SBX509.Unit.vrUnknownCA, but again I believe this is because it is a CA cert, am I correct?

I've tried adding this code into the OnCertificateValidate handler:

Code
if (Certificate.CAAvailable)
                {
                    CertificateValidator.CheckOCSP = true;
                }
                else
                {
                    CertificateValidator.CheckOCSP = false;
                    CertificateValidator.CheckCRL = false;
                }


Am I along the right track? It is still replying with the same issue.

At the moment in my OnAfterCertificateValidation handler I am setting the Validity to true if there is no CACert to verify with however this is not secure....

I'm assuming this is another issue with the validateForSSL method?

Thanks,
Sam
#15526
Posted: 01/17/2011 07:52:52
by Eugene Mayevski (EldoS Corp.)

Certificate chain must be built starting from end-entity certificate and up to self-signed trusted root CA certificate. Sometimes root CA certificate is not available, but some intermediate CA is trusted. In this case there's no need to build a chain up to the root.

In your case you probably have an incomplete chain -- your CA certificate could not be validated property cause it is not trusted explicitly and it's own CA could not be found as well.

You need to look not at validation now, but at building a chain first of all.


Sincerely yours
Eugene Mayevski
#15529
Posted: 01/17/2011 10:58:00
by Sam Barber (Basic support level)
Joined: 01/11/2011
Posts: 7

Thanks Eugene,

I've had a look at the documentation and I am still struggling to work out if there best practice way of doing this, are there any of the samples which cover this comprehensively?

At the moment I am using the MemoryCertStorage.Validate Method to validate the certificates that do not have a CA Certificate.

Again, I have pretty much just ripped everything out of the SimpleFTPS example so I was hoping everything would already be covered, so far from what I understand something is going wrong with the ValidateForSSL method but reading your how-to for validating certs - http://www.eldos.com/documentation/sbb/documentation/ref_howto_pki_cert_validate.html - it doesn't even mention this method.

Sorry if I'm missing something completely!
Here's my code for the event handlers:

Code
private void Client_OnCertificateValidate(object Sender, SBX509.TElX509Certificate Certificate, ref bool Validate)
      {
         TSBCertificateValidity Validity = TSBCertificateValidity.cvInvalid;
         int Reason = 0;
         if ((Certificate.Chain == null) || (Certificate.Chain.get_Certificates(0) == Certificate))
         {
                //if (Certificate.CAAvailable)
                //{
                //    CertificateValidator.CheckOCSP = true;
                //}
                //else
                //{
                //    CertificateValidator.CheckOCSP = false;
                //    CertificateValidator.CheckCRL = false;
                //}

            CertificateValidator.ValidateForSSL(Certificate, Client.RemoteHost, Client.RemoteIP, TSBHostRole.hrServer, null, false, false, DateTime.Now, ref Validity, ref Reason);
            Validate = (Validity == TSBCertificateValidity.cvOk) || (Validity == TSBCertificateValidity.cvSelfSigned);
         }
         else
            Validate = true;

            if (Validate == false)
            {
                Log("RemoteHost: " + Client.RemoteHost, false);
                Log("Reason: " + Reason.ToString(), false);
                Log("SelfSigned?: " + Certificate.SelfSigned, false);
            }
      }

        private void Client_OnAfterCertificateValidation(object Sender, TElX509Certificate Certificate, TElX509Certificate CACertificate, ref TSBCertificateValidity Validity, ref int Reason, ref bool DoContinue)
        {
            string[] status = { "Success", "Malformed request", "Internal error", "Try later", "", "Signature required", "Unauthorized" };

            byte[] Reply = null;
            int res;
            short ServerResult = 0;
            int ReasonNew = 0;
            TSBCertificateValidity ValidityNew;
            int i;

            //Reason = 0; //get rid of!

            if (Certificate != null && CACertificate != null)
            {
                LoadCertificates(Certificate, CertStorage);

                if (CACertificate != null)
                    LoadCertificates(CACertificate, IssuerCertStorage);

                OCSPClient.IncludeSignature = true;
                OCSPClient.Nonce = SBUtils.Unit.BytesOfString(DateTime.Now.ToString()); // In real life use some cryptographically strong random data

                OCSPClient.URL = Certificate.Extensions.AuthorityInformationAccess.get_AccessDescriptions(0).AccessLocation.UniformResourceIdentifier;

                if (OCSPClient.IncludeSignature)
                {
                    LoadCertificates(@"C:\Code\MISC\Keys\SAML2 Testing\TBX_SAML2_IdP_Testing.cer", SigningCertStorage);
                }

                res = OCSPClient.PerformRequest(ref ServerResult, ref Reply);


                if (res != 0)
                {
                    switch ((uint)res)
                    {
                        case SBOCSPCommon.Unit.SB_OCSP_ERROR_NO_PARAMETERS:
                            Log("URL not specified", false);
                            break;
                        case SBOCSPCommon.Unit.SB_OCSP_ERROR_NO_REPLY:
                            Log("Failed to retrieve a reply from OCSP server", false);
                            break;
                        case SBOCSPCommon.Unit.SB_OCSP_ERROR_WRONG_SIGNATURE:
                            Log("Reply from OCSP server contains invalid or broken signature", false);
                            break;
                        case SBOCSPCommon.Unit.SB_OCSP_ERROR_NO_CERTIFICATES:
                            Log("No certificates have been specified for checking", false);
                            break;
                        case SBOCSPCommon.Unit.SB_OCSP_ERROR_NO_ISSUER_CERTIFICATES:
                            Log("No issuer certificates were found", false);
                            break;
                        default:
                            Log(System.String.Format("Error {0} happened when trying to check certificate status", res), false);
                            break;
                    }
                }
                else
                {
                    Log("The server replied with the following status: " + status[ServerResult], false);
                    if (ServerResult == SBOCSPCommon.Unit.oseSuccessful)
                    {
                        // First validate the server certificates
                        Validity = TSBCertificateValidity.cvStorageError;
                        if (OCSPClient.ReplyCertificates.Count == 0)
                            Log("The server didn\'t include signing certificates to the reply", false);
                        for (i = OCSPClient.ReplyCertificates.Count - 1; i >= 0; i--)
                        {
                            Validity = OCSPClient.ReplyCertificates.Validate(OCSPClient.ReplyCertificates.get_Certificates(i), ref Reason, System.DateTime.Now);
                            if (Validity == TSBCertificateValidity.cvInvalid)
                                break;
                        }
                        if (Validity == TSBCertificateValidity.cvInvalid)
                            Log("One of certificates, used to sign the reply, is not valid", false);

                        // Next, check certificate's status
                        for (i = 0; i < CertStorage.Count; i++)
                        {
                            switch (OCSPClient.get_CertStatus(i))
                            {
                                case SBOCSPCommon.Unit.csGood:
                                    Validity = TSBCertificateValidity.cvOk;
                                    Log(String.Format("Certificate {0} is ok", i), false);
                                    break;
                                case SBOCSPCommon.Unit.csRevoked:
                                    Log(String.Format("Certificate {0} has been revoked on {1}", i, OCSPClient.get_RevocationTime(i).ToString()), false);
                                    break;
                                case SBOCSPCommon.Unit.csUnknown:
                                    Log(String.Format("Certificate {0} is not known to OCSP server", i), false);
                                    break;
                            }
                        }
                    }
                }

            }
            else
            {
                LoadCertificates(Certificate, CertStorage);
                Validity = CertStorage.Validate(Certificate, ref Reason, Certificate.ValidFrom);
            }
              //  Validity = TSBCertificateValidity.cvOk;

            //SBX509Ext.TElGeneralName name = Certificate.Extensions.AuthorityInformationAccess.get_AccessDescriptions(0).AccessLocation;
            //SBX509Ext.TElGeneralName caName = CACertificate.Extensions.AuthorityInformationAccess.get_AccessDescriptions(0).AccessLocation;
            //Log(name.UniformResourceIdentifier, false);
            //Log(caName.ToString(), false);
        }


Cheers,
Sam
#15530
Posted: 01/17/2011 11:20:21
by Eugene Mayevski (EldoS Corp.)

TElX509CertificateValidator class encapsulates everything described in the how-to. If you use this class, you don't need to perform any manual validation.

As for understanding -- SecureBlackbox documentation is not a book on cryptography but a reference for the component library. It *expects* understanding of cryptography, not teaches it. So I'd recommend that you start not from documentation but from the books on PKI.


Sincerely yours
Eugene Mayevski
#26464
Posted: 09/16/2013 12:59:16
by Paul Severini (Standard support level)
Joined: 08/12/2013
Posts: 5

Eugene,

I'm not a cryptography or security expert, just a plain old C# developer. I think you should add a professional level support subscription for developers who don't have a cryptography or security background. We would be willing to pay a little more for your expertise.

Would that be something you would consider? You can't make every developer a cryptography expert over night. We have project deadlines and we don't have the luxury of training ourselves on everything there is to know about security or cryptography. I wish I had the time, but my boss will not give it to me.


I appreciate your concern, but I think it's unrealistic to think every developer should have a cryptography background. Why don't you sell your expertise? We certainly don't want to take advantage of your time.
#26465
Posted: 09/16/2013 13:06:49
by Paul Severini (Standard support level)
Joined: 08/12/2013
Posts: 5

Eugene,

The sample link to your documentation above assumes that I have a certificate to work with. I don't have a X509 certificate from the store just yet. I was trying to get a certificate in the Windows store and that's why I logged a ticket because the Certificates method in C# does not work like you stated.

What's the correct way to get a certificate or collection of certificates from the Windows store?


Code

Your sample code:
private void Client_OnCertificateValidate(object Sender, SBX509.TElX509Certificate Certificate, ref bool Validate)
      {
         TSBCertificateValidity Validity = TSBCertificateValidity.cvInvalid;
         int Reason = 0;
         if ((Certificate.Chain == null) || (Certificate.Chain.get_Certificates(0) == Certificate))


My Code:
What do I need below to get the code below to retrieve a certificate from the current Windows store?

var wcs = new SBWinCertStorage.TElWinCertStorage();
   wcs.ReadOnly = true;
   wcs.AccessType = SBWinCertStorage.TSBStorageAccessType.atLocalMachine;
   wcs.SystemStores.Add("MY");
   wcs.PreloadCertificates();
    
   context.Instance.TraceInformation("Trace: Certificate count= " + wcs.Count + "\r\n");
   
   for (int x=0;x<wcs.Count;x++)
   {
      <-- what do I need here ?? -->
   
   }
#26466
Posted: 09/16/2013 13:16:23
by Ken Ivanov (EldoS Corp.)

Hello Paul,

What exactly certificate do you need to retrieve and for what purpose? Normally you do not need to access the 'MY' (Personal) store in order to validate server-side certificates, as this store contains certificates belonging to the local computer user. Instead, validation usually involves certificates from CA and ROOT stores that are used to build and validate chains for server-side certificates.

Your initialization code is generally correct; you might need to assign SBWinCertStorage.TSBStorageAccessType.atCurrentUser to the AccessType property in order to access certificates from the Current User view of the store though.
#26467
Posted: 09/16/2013 13:26:32
by Paul Severini (Standard support level)
Joined: 08/12/2013
Posts: 5

Eugene!,

I know what's causing this issue. You guys think I'm crazy, but the member is not visible in the IDE. I originally looked for the member, but could not find it. Why are these members hidden from the intellisense in our IDE?

Geez, all of this because the member is not visible in my IDE.


I would have easily understood your response if I could just see the member in my IDE.


That's why we're going in circles here.
Also by EldoS: MsgConnect
Cross-platform protocol-independent communication framework for building peer-to-peer and client-server applications and middleware components.

Reply

Statistics

Topic viewed 6277 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!