… under a very loose definition of “fun.”
This one sent me down a rabbit hole for a few hours, so I figured I’d write it up for my own future reference, and maybe spare others from some pain.
I have an OwnCloud server with an SSL certificate signed by my own CA cert, and I was trying to set up DAVdroid to sync my calendar and contacts against it. First, I had to get my CA certificate installed on my phone, which goes something like this:
- Get the CA cert into DER format, with a .cer or .crt file extension. The magical OpenSSL command-line incantation will look something like:
openssl x509 -outform der -in certificate.pem -out certificate.crt (no, I don’t know why Android can’t accept PEM format. Google says you need DER or PKCS#12.)
- Get the CA cert onto internal storage. Post it somewhere you can download it, or copy it to an SD card and then to internal storage. (No, I don’t know why you can’t load it directly from the SD card. Because Google, I guess.)
- Go to
Settings > Personal > Security > Credential storage > Install from storage. Android should find the cert and prompt you to install it.
That all went well enough, and Android told me the cert was successfully installed. Weirdly, though, I didn’t actually see it listed under the user-installed CA list. It also wasn’t actually working. I browsed to my OwnCloud site and got a certificate error. DAVdroid also refused to connect to my OwnCloud server, reporting only “Cannot verify hostname.”
(insert 80s-style montage representing too much time spent researching and reading documentation)
Eventually it became clear that my CA cert was in X.509 v1 format, and Android insists upon X.509v3 format, with the
basicConstraints=CA:true extension. This appears to be an Android-specific quirk; I’ve never had a problem importing my CA cert into a web browser.
Solving the problem required regenerating my CA cert with the required X.509v3 extension. That, in turn, required digging into the truly awful OpenSSL documentation to figure out how to accomplish such a seemingly simple task. In the end, I couldn’t find a way to specify the
basicConstraints=CA:true extension on the command line; instead I added this stanza to my openssl.cnf file:
Then, I generated a new CA cert, adding
-extensions x509v3_CA to the command-line arguments. Generated a new CSR, signed it with my new CA cert, juggled all the files to the right places, and imported the new CA cert into my phone. Sure enough, it imported successfully, showed up in the list of user-installed certs, and made the Android browser and DAVdroid happy.
It appears that there may be a way to add this extension to an existing CA cert to avoid regenerating everything, but (A) I was already far enough down the rabbit hole, thanks, and (B) I only needed the one certificate for my own personal use.
Google had a bug report opened for this issue, but closed it as “WorkingAsIntended”. If you say so, guys…
I’m told that the process for adding a CA cert to an iPhone is even more tortuous (torturous?), but I have no plans to go down that road.