How safe are client SSL certificates in a mobile app?
Are you doing client side authentication with certificates over SSL? Not that it really matters for this question. Any private keys you store in your app is accessible to an attacker. Each client should have it's own certificate and key pair, to prevent a mass compromise. Your server should also enforce protections, ensuring a compromised client can't just request anything.
This is true for any authentication scheme. If you embed passwords, API keys, decryption keys, whatever. Anything on the device should be assumed to be accessible.
The added security from certificates in part comes from there being nothing to brute force. If you went the username/password route for each clients, passwords can be guessed. Same with API keys (albeit they are longer and harder). With certificates, it's an entirely different class of attacks, and a considerably harder problem.
But, most importantly, the backend service shouldn't allow the app to do anything it wouldn't normally do.
Now, dealing with certificates, you're going to have a whole host of other problems. You probably want to sign each client certificate with your self-signed CA cert. Managing that CA cert can be problematic, depending on your use case. Are you going to generate these client certs on the fly, or manually yourself? Meaning, is this an app that a million people can download, and you need an automated system for generating them? Or is this a private/internal app that you personally will handle generating certs?
The certificate is harmless. It is the private key that needs protection, and it is only as safe as the device itself, no safer. Distributing the certificate and private key with the application just means that anyone who has the application has the key, so it doesn't provide you any security whatsoever. I think you need some kind of post-install registration step.
Typically, client SSL certificates are stored in keystores (BKS formatted in the case of Android) and the keystore is included as a resource within your APK. Keystores are encrypted and protected with a password. So, that client certificate cannot be readily extracted from an APK, as it is stored in an encrypted form.
Now...what do you do about the password? Here is the crux of the matter and you have two alternatives.
If you want your application to be able to communicate with the server (so, to be able to access the certificate) without user interaction, you will need to embed the password into your application and then, yes, an attacker could reverse engineer your code to find it, grab the keystore, and then decrypt it to recover the certificate. You can apply techniques like obfuscating your code so that it is harder for an attacker to do so, but this will just slow someone down and not prevent it.
Your alternative is to prompt the user for a password every time your application communicates to the server and use that to decrypt the keystore (or ask when the app starts and cache the certificate for a certain amount of time). The advantage here is that if someone reverse engineers your APK, they will find the encrypted keystore and no password so your certificate is safe. The disadvantage is having the user provide the password.
Which approach is best? It completely depends on the sensitivity of the data you are concerned with and the level of risk you are willing to accept. Only you can answer that question.