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