Topic: How to use the VerifyCallback?

Hello,
I am writing a 802.1X handshake client and need to verify the cert chain.  If I leave the ssl_set_verify() as NULL, it fails due to a date issue, since the embedded device has no RTC.

So I need to verify that the signer for the server certificate matches the CA which I have on the client device.  And ignore if the cert date is not valid, because we can't get the time until after the 802.1X authentication occurs.

Here's my test process

  • A CA where we are acting as our own Certification Authority (call it "CA1")

  • A fabricated cert on the server which is signed by CA1  (call it "certificate")

  • A fabricated different CA which doesn't apply to anything (call it "CA2")

(CA2 is to mimic someone attaching the device to a different 802.1X network where the server sends a cert that we don't have the correct CA for)

My goal is to ignore the errors related to the time validity, but reject if the server certificate was issued by CA "company1", while the client is using a CA from "company2"

Loading the PEM/DER data is not a problem. 
But am I loading it for the correct usage, and using the correct API calls?

I registered the callback using

SSL_set_verify(ssl, SSL_VERIFY_NONE, certVertify);

I load the CA using

SSL_user_certificate_ASN1(ssl, cabuffer, calength);

I also load the clients cert and key since the server needs peer authentication

SSL_user_certificate_ASN1(ssl, clientbuffer, clientlength);
SSL_user_certificate_ASN1(ssl, keybuffer, keylength);

If I completely ignore any errors on the client side, the 802.1X validation occurs fine, and it lets the device into the network.

But I need to be able to verify in the client that the server certificate is signed by the CA that is on the client.

The callback code is:

static int certVertify(int preverify_ok, X509_STORE_CTX *x509_ctx) {
        X509 *err_cert;
        int err, depth;
        char buf[256];
        const char *err_str;

        printf("------------------\nVerify Called\n");
        err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);

        err = X509_STORE_CTX_get_error(x509_ctx);
        depth = X509_STORE_CTX_get_error_depth(x509_ctx);

        err_str = X509_verify_cert_error_string(err);
        printf("The error is: %ds  Depth: %d \n",err_str , depth);
        X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
        printf("Cert is %s\n", buf);
        ...

Here's what happens and in some of these case, I don't understand what it's doing or why:
When I load the CA1 (the real one) and the time is correct, the callback gets called twice.  I am logging each time the verification callback occurs, and getting the error code, the depth, and certificate that the callback is referring to.

Error: 0  Depth: 1  Cert is CA1
Error: 0  Depth: 0  Cert is the certificate

That's fine. Makes sense.  Except we won't have the correct time in real life.

When I load the CA1 (the real one) and the time is INCORRECT, the callback gets called four times:

Error: certificate is not yet valid   Depth: 1   Cert is CA1
Error: certificate is not yet valid   Depth: 1   Cert is CA1
Error: certificate is not yet valid   Depth: 0   Cert is the certificate
Error: certificate is not yet valid   Depth: 0   Cert is the certificate

The "not yet valid makes sense", but why is it called 4 times?  Twice for each depth?

Next, when I load the CA2, which is the incorrect certification authority. This would a use where the device is attached to a network who has the incorrect CA.  And with the correct time, I get the following:

Error: Self Signed cert in chain  Depth: 1   Cert is CA1
Error: Self Signed cert in chain  Depth: 1   Cert is CA1
Error: Self Signed cert in chain  Depth: 0   Cert is the certificate

Okay, why is the callback handing me the CA from the server, and yet saying nothing about the certificate not being signed by the CA2 that I loaded?

Why is it telling me that CA1 (the actual signer of the certificate) is self signed?

Why is it calling the depth 1 twice?

Next, when I load the CA2, which is the incorrect certification authority, and the time is INCORRECT, I get the following:

Error: Self Signed cert in chain  Depth: 1   Cert is CA1
Error: certificate not yet valid    Depth: 1   Cert is CA1
Error: certificate not yet valid    Depth: 1   Cert is CA1
Error: certificate not yet valid    Depth: 0   Cert is the certificate
Error: certificate not yet valid    Depth: 0   Cert is the certificate

Now why are there 5 calls to the callback?

Any explanation about this would be greatly appreciated.

-Scott

-Scott
<Code shown is not to scale>

Share

Re: How to use the VerifyCallback?

Update...
The questions still stand, but I realize the CA is loaded in the

X509_Store_new();  

And it not necessary to load into

SSL_user_certificate_ASN1();

That was already occurring in another part of my code.

So that portion of my post changes. However the behavior of the certVertify callback remains not understood.

-Scott
<Code shown is not to scale>

Share

Re: How to use the VerifyCallback?

Hello Scotty,

The callback is being triggered for each error encountered. There are checks for "valid-from" and "expiration", each could be triggered if the system time and date are invalid.

You can override the date errors like this:
https://github.com/wolfSSL/wolfssl/blob … st.h#L2829

Or is you know the time will always be invalid, you can bypass cert date checking in the wolfSSL config by defining `NO_ASN_TIME`.

I'll review the CA signer issue with the team tomorrow. I suspect it could be the order that the certs are loaded. Could you please enable debug logging and share the log showing the signer error?

Thanks,
Eric @ wolfSSL Support