Search code examples
androidc++opensslgsoap

How to store and load cacerts.pem for gSoap-OpenSSL Android app


I am working on a C++ Android app that uses gSOAP with OpenSSL. To enable OpenSSL to validate the server certificate I need to provide it with location for the cacerts.pem file, otherwise all HTTPS connections fail.

My question is: What is the right way to store and load cacerts.pem on Android?

  • I am able to copy cacerts.pem into the APK root by placing it in src/resources or res/raw/ or assets/. But SSL_CTX_load_verify_locations(ctx, "cacerts.pem", nullptr) fails to find the file. How can I make OpenSSL be able to read the PEM file inside APK?

  • Is there a way to store cacerts.pem as a string buffer and thus avoid carrying it in the APK?

My app needs to talk to sharepoint online sites (https://*.example.com/)


Solution

  • What is the right way to store and load cacerts.pem on Android?

    You must load the one CA needed to verify the host's certificate.

    You can load intermediates required to build a path from the host to the CA, but its optional. A well configured server will send the needed intermediate certificates, but not all of them are well configured.

    You don't load cacert.pem or equivalent. cacert.pem contains hundreds of certifcates, and all of them but one are wrong.


    Do I need to copy cacerts.pem somehow into the .APK (how to do this?) and provide path to the file to SSL_CTX_load_verify_locations()?

    No. You usually need one certificate, and that's the CA that certifies the host's certificate. It can be a public CA, like Comodo, or it can be a private CA internal to the organization.

    You usually place it in the res/ or assets/ folder. Also see Difference between /res and /assets directories on Stack Overflow.


    Is there a way to store cacerts.pem as a string buffer and thus avoid carrying it in the .APK?

    Yes, but you might have to take the string, write it to the filesystem, and then use the file for SSL_CTX_load_verify_locations. So in the end, its probably best to place it in res/ or assets/.


    ... sharepoint online sites (https://*.example.com/)

    One important note for hostname validation. OpenSSL 1.0.2 and earlier does not perform name matching. It performs other customary checks, like ensuring a path exists from the end-entity certificate (the host) to the CA certificate (the root of trust) and the certificate is not expired. But it does not perform the hostname matching.

    OpenSSL 1.1.0 does perform hostname matching. It will be released soon.

    As a stop gap, you usually lift the missing code from a library like cURL. cURL performs the hostname matching, and Daniel Stenberg is happy to share the code. I think its located in ssl.c, if memory serves me.

    Also see TLS Client on the OpenSSL wiki.