How to get the CA Certificate Used to Validate Client Certificate programmatically - c++

In a server application, once a connection has been established I can grab the client certificate from the SSL * I have. Is there a way to find out which CA I used to validate that certificate?

You can use the SSL_get0_verified_chain() function for this purpose. See the documentation here:
https://www.openssl.org/docs/man1.1.1/man3/SSL_get0_verified_chain.html
Note that this function was first introduced in OpenSSL 1.1.0, so this won't work in OpenSSL 1.0.2.

This post seems on point:
Find client certificate information from server in OpenSSL
Since SSL_get_peer_certificate returns an X509 cert, I would expect that the cert chain would be included (you couldn't handle a CRL properly without it, I'd think)?

Related

libcurl's default behavior for certificate pinning

We are sending requests to a server using libcurl (7.51.0). We have a .pem file where we have a set of CA certificates that are being set via CURLOPT_CAINFO option.
curl_easy_setopt(mpCURL, CURLOPT_CAINFO, "/usr/certs/certificates.pem");
Now, I would like to figure out whether the CA certificates present within the .pem are pinned or not. How do I achieve this?
Also, according to the answer in the question Public key pinning in curl does not work without using certificates from the system, it seems like as long as the CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST options are left as defaults and a set of CA certificates are provided via CURLOPT_CAINFO, cURL library implements CA certificate pinning by default. Is that correct? Does that mean that libcurl pins all the certificates that are present in the .pem file?
I confirmed that CURLOPT_SSL_VERIFYPEER's default value enables CA pinning by default. As a result, it uses the certificates mentioned in CAPATH for CA pinning.

MITM proxy, TLS 1.2 Certificate verification failed

Trying to create my own simple MITM-proxy for the specific app which using TLS 1.2 protocol and connecting to several IP addresses, however got in stuck with the error in the app log "Certificate verify failed". How to solve this problem?
The app using about the following code to check the cert:
X509* cert = SSL_get_peer_certificate( ssl );
X509_STORE_CTX * xCtx = X509_STORE_CTX_new();
X509_STORE_CTX_init( xCtx, (X509_STORE*)Store, cert, NULL );
int res = X509_verify_cert( xCtx );
if( !res ) { /*Certificate verify failed*/ };
I did the following steps to achieve the result:
Created CA root key and self-signed certificate according to this manual. It is a bit outdated, so i have made some changes like md5 to sha256, also I didn't use pass phrase, used different key size and other minor changes.
Created proxy key and certificate using the above Root CA to sign it.
Both certificates have been added to the Local Computer Certificates in Personal and Trusted Root Certification Authorities (not sure if this was necessary). Btw, I'm using Windows 10.
Wrote a simple proxy server using sample code from here. Cert.pem and Key.pem took from the second step.
Changed all IP addresses in the app to 127.0.0.1:443 to see if TLS connection established successfully and we can receive first message with an Application Data.
I believe that connection established properly, because WireShark shows common sequence for establishing a TLS connection: Client/Server hello, Certificate, Client key exchange, two encrypted handshake messages. Moreover, using OpenSSL for testing connection:
openssl s_client -connect localhost:443
allow me to write some message and later successfully receive it using SSL_Read() in proxy server. However, there are some errors:
verify error:num=20:unable to get local issuer certificate
verify return:1
verify error:num=21:unable to verify the first certificate
verify return:1
Verify return code: 21 (unable to verify the first certificate)
Using OpenSSL client to directly connect to the original IP addresses give the same errors, but application works great.
Also the output:
openssl verify -CAfile "signing-ca-1.crt" "cert.crt"
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
e:\MyProg\SSL_serv\Debug\cert.crt: OK
It seems that I missed something important. Could you please tell me how to solve this problem with cert?
One of the very purposes of having certificates, along with certificate authorities, is to prevent MITM. The app you are trying trick does the proper thing and checks the certificate. And it doesn't like your's. Its really that simple.
Is it possible to circumvent it and run MITM on an app anyway? Absolutely! Is it going to be easy? Probably not. What you need to do is to patch the app and remove this certificate check.

Difference between x509_store_add_cert & ssl_ctx_use_certificate?

I'm trying to load multiple certificates into an SSL_CTX.
Looking at the documentation, I was able to establish SSL connection using these 2 ways:
Create an X509_STORE, add certificates to the store, and then load the cert store into the SSL_CTX using SSL_CTX_set_cert_store.
Call SSL_CTX_use_certificate(ctx, cert) multiple times
Is there a difference between these two? I saw on StackOverflow somewhere that SSL_CTX_use_certificate does not work with self signed certs? (Loading CA certificate from memory) Why? I don't see this on the documentation anywhere. (What does it mean to be self signed?)
*also for #2, does calling SSL_CTX_use_certificate multiple times replace the existing certificate? Would I need to call SSL_CTX_add_extra_chain_cert?
The X509_STORE is used for building the certificate trust chain during certificate validation. Thus, any certificates added by X509_STORE_add_cert are used when validating the peer certificate.
SSL_CTX_use_certificate instead is used to set the local certificate used for authentication against the peer, i.e. this is to set the server certificate at the server and the client certificate at the client. It must be accompanied by a function to set the private key, like SSL_CTX_use_PrivateKey. SSL_CTX_use_certificate can be called multiple times and will either replace the existing certificate or add another one: i.e. one might have both an RSA and a ECDSA certificate at the same time with newer versions of OpenSSL.
SSL_CTX_use_certificate does not work with self signed certs?
OpenSSL does not care if the certificate is self-signed or not when using SSL_CTX_use_certificate. The communication peer which receives the certificate as authentication will hopefully care though and might complain since no local trust anchor is found to validate the certificate.

How to verify certificate with ocsp using openssl

I have a problem.
I am using openssl for validate my cert - x509_verify_cert(). But this function doesn't use ocsp. So it can be a problem if there is no crl.
In openssl errors i found this define - x509_err_ocsp_verify_needed, but i don't understand how it uses.
It seems that may be exists some kind of callback for my connecting to ocsp server function or something like that.
Also i found it which i can use, as i understand, for my own validate function, but i want only ocsp check.
So my question is: is it possible ask openssl use ocsp for validation and how?
It is possible :
openssl ocsp -issuer certchain.pem -cert cert.pem -text -url <the ocsp responder URL>
Some links to articles with more details:
https://raymii.org/s/articles/OpenSSL_Manually_Verify_a_certificate_against_an_OCSP.html
https://akshayranganath.github.io/OCSP-Validation-With-Openssl/
OpenSSL API does not provide a single API to do OCSP validation. The OpenSSL API provides the primitives so that you can implement your own validation. There are details you need to fill to the implementation which may depend on your situation you are trying to solve.
I would suggest that you get to know the openssl ocsp command as a basis of your understanding. Reading the links from Sanjeev's answer gives you examples of using this command as well.
To implement OCSP validation you will need to:
Extract server and issuer certificates from somewhere (SSL connection most likely)
Extract the OCSP server list from the server certificate
Generate a OCSP request using the server and issuer certificates
Send the request to the OCSP server and get a response back
Optionally validate the response
Extract the certificate status
Optionally you can also cache the result with the response update date range so that you can shortcut the above procedure if you see the certificate again.
You can also group a bunch of server certificates to the same OCSP server into a single request as well.
Of note is that the OCSP server link may not be HTTP and you may need to support whatever link type the certificate may have. For example in windows AD enterprise setups, the server OCSP may only have LDAP OCSP server links.
You may also like to see my answer to a question where I go into code examples of OCSP request and response handling.
UPDATE:
If you want to check the whole chain, you will have to do the above one certificate at a time (although the certificates operations can be overlapped). As far as I know, there is no way to check a whole chain at once. Also, you may find that a lot of intermediate certificates don't provide OCSP links anyway so there is no way to check. If you need to do this then it would be a good idea to cache the results as you will come across the same intermediate certificates all the time. In fact you could schedule to do this ahead of time for "known" intermediate certificates that you come across all this time.
You also keep pointing to "x509_verify_cert" check I quote:
Applications rarely call this function directly but it is used by
OpenSSL internally for certificate validation, in both the S/MIME and
SSL/TLS code.
So you shouldn't be calling this yourself anyway.
It seems that may be exists some kind of callback for my connecting to ocsp server function or something like that.
X509_STORE_CTX_set_verify_cb - used to set a callback to do your own custom verification - used a lot in server SSL setups
X509_STORE_CTX_set_ex_data - used to add custom argument values used by the callback
X509_VERIFY_PARAM_set_flags - used to setup flags (e.g. X509_V_FLAG_CRL_CHECK or X509_V_FLAG_CRL_CHECK_ALL)
In openssl errors i found this define - x509_err_ocsp_verify_needed
X509_V_ERR_OCSP_VERIFY_NEEDED is defined and never used in the openssl codebase. It is meant to returned from a verify callback function that the user provides (i.e. X509_STORE_CTX_set_verify_cb) to indicate that verification should fail with that error. What you do with that information is up to you. If you supply a callback and return that error from a openssl SSL connection that the SSL connection will terminate.
Also of note, if you do add a custom verification callback that does do full OCSP checking, it will slow down the SSL connection setup a lot. This is why most browsers don't do this by default as it slows down the user experience to much.

How to establish a bi directional connection with ssl certificate?

I'm trying to connect with one of my client to call api methods from their server, the client want to have a bi-directional commnunication, they shared their security certificate which contains CACert.crt, another file with .crt, .key, .p7b, .pfx files. Now They want us to share our certificate. I've following questions:
How I install their certificate?
How I can generate my certificate? Do I need to purchase certificate for this or I need to generate something based on their certificate?
They mentioned about DataPower public certificate. After Googling, I found Datapower is from the IBM, can I create a free certificate from it?
I'm absolutely new to this, tried to google a lot, but couldn't make much sense.
It sounds like your client wants you to use a client certificate. They've provided you with a CA for you to use; just use that to fulfill the signing request for the certificate you generate.