Why is CARoot handling different in Servers verifying Clients versus Clients verifying Servers? Is Server verifying Clients broken in dual-cert-type installations?
Its been about 12 years since my last post here. So I apologize in advance if I trample anyone/anything due to any changes in etiquette since back then.
I wonder of anyone can shed light on why OpenSSL treats the two CARoot file collections used in Servers and Clients differently?
Is it simply for performance purposes?
The reason I ask is that I have found a difference in behaviour between the two implementations, which on the surface at least looks like a bug - or at least a missed piece of implementation. It has had an unwanted effect in my testing setup.
This issue concerns the handling of multiple types of CARoot and Intermediate Certs held in a single PEM file.
I'm using 1.0.2 for debugging, but the following code is also in 1.1.0 and 1.1.1.
All of the following takes place in ssl/ssl_certs.c.
For Clients the CARoot collection's cert store generator
works as follows:
SSL_CTX_load_verify_locations() calls X509_load_cert_crl_file() to load a file into a ctx based store.
In my test case all 6 CARoot and Intermediate certs are loaded.
The Server's side however takes a completely different route to do a very similar task. It also stores the results in a different place.
SSL_load_client_CA_file() is the Server's CARoot cert collection generator
checks each new cert being loaded against hashes of existing Subject_Name entries of certificates already loaded into the stack of certs and discards duplicates.
This check is done using X509_get_subject_name() and the comparison is done using sk_X509_NAME_find()
In my test case only 5 of the 6 certs are loaded. I think this is wrong.
The same CARoot collection PEM file is being used in both cases.
My problem is triggered because I am testing a dual RSA/ECDSA
implementation on a single Server endpoint, and I also have ECDSA and RSA
All the certs involved are generated for the test scenario using OpenSSL. Not commercial certs.
4 levels of intermediate RSA certs.
The RSA CARoot cert
The ECDSA CARoot cert
Servers and Clients are generated at various levels of the intermediate collection. Plus directly by the ECDSA CAroot.
The issue is that all unidentified/un-certified Clients can connect to Servers, but Servers will reject some certified Clients when asked to verify them.
Depending upon the order of the content in the CARoots PEM file the rejected Clients will change.
The problem is that the CARoot cert is available in both signature types - but the rest of the identification information in the two certificates is pretty much the same content. The time stamps change of course, but its identifying the same CA. Just using different signature types.
Because of the Server side test of the SubjectName, the subject name of whichever cert is second in the PEM file will be compared with the previously loaded certificate and ignored. This preventing Clients identified by that CA from being verified.
This looks like a bug in OpenSSL based upon the assumption that the SubjectName hash is enough of a unique identifier. Which was probably true back when all certs were RSA certs. Nothing else needed checking.
Surely a more accurate approach today would be to combine the SubjectName with the certificate signature type when creating the hash values. Or to simply do what the client side does and avoid duplication checks - now I do know that the latter is not a sensible action for performance reasons.
BTW I realize that simply changing the ID to "CA Name RSA" and CA Name ECDSA" would most likely solve this for my test case. However I don't think I should need to do this. Or is this a miss-understanding on my part?