How can I import a Root CA that's trusted by Chrome on Android 11



  • I have a Root CA (airgapped, openssl) that I use for a lot of internal lab projects.

    In the past, I've just imported the CA cert into the User credentials store on Android and the system began trusting it immediately.

    I just wiped my phone and now, on Android 11, I'm unable to get this Root CA trusted the way it was before.

    The CA cert definitely has the CA:TRUE extension:

    $ openssl x509 -in root.crt -noout -text|grep -B2 TRUE
            X509v3 extensions:
                X509v3 Basic Constraints: 
                    CA:TRUE
    

    The Server cert that's presented in the SSL exchange matches the DNS name and also includes the same name in the SAN extension:

    (...)
            Issuer: O =  Lab Root CA, emailAddress = , L = , ST = , C = US, CN =  Lab Root CA
            Validity
                Not Before: Aug 13 11:39:55 2020 GMT
                Not After : Aug 13 11:39:55 2023 GMT
            Subject: C = US, ST = , CN = 
    (....)
                X509v3 Subject Alternative Name: 
                    DNS:
    

    The server I'm testing with correctly chains the cert in the TLS response, and this setup works great across a bunch of browsers and OS combinations in the desktop world (and worked until recently on Android).

    I've tried the following:

    • Import the Root CA Certificate through the normal "Import from SD Card" method. The CA imports properly, but Chrome still gives invalid authority browser warnings.

    • (Rooted) moving the imported cert from the user /data/misc/user/0/cacerts-added imported credentials folder to /system/etc/security/cacerts. The CA appears correctly in the "System" tab of Trusted Credentials, but still doesn't work in chrome

    • Manually crafting the DER-encoded file into the System cacerts folder. Chrome still doesn't work.

    • Following the example of some PEM-encoded trusted CA certs already on the system, crafting my own and putting it into System cacerts. Chrome still doesn't work.

    • I tried using a Magisk module to move User trusted certs to the System store. This module worked as described, and moved my Root CA into the System tab, but Chrome still didn't want to trust for SSL and continues to give out browser warnings.

    Some other observations:

    • Running curl -vv https:// via adb constantly complains about SSL certificate problem: self signed certificate in certificate chain even though the CA that the certificate is signed by is in the Trusted credentials store.
    • The CA trust chain definitely works fine in desktop browsers, and via openssl s_client on a desktop (Verify return code: 0 (ok) when the Root CA is imported into the desktop trust)
    • I've cleared Chrome's app storage every time I go to test after making a change. No dice.

    Is there anything else I can try or a setting that I've missed? It's very annoying to not be able to manage trusted Root CAs on Android 11 like I used to.

    I'd rather not have to turf the whole airgapped, comprehensive SSL CA that I've set up for something like Let's Encrypt just because of Android compatibility so please don't suggest that as an alternative. There are lots of internal-only endpoints in this lab and my public DNS provider doesn't support automation for dns-01 ACME, so it would be a really big pain to proxy and juggle these certs.

    Here's a sample of what one of the server certs looks like:

    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number: 4123 (0x101b)
            Signature Algorithm: sha256WithRSAEncryption
            Issuer: O =  Lab Root CA, emailAddress = , L = , ST = , C = US, CN =  Lab Root CA
            Validity
                Not Before: Dec 23 13:06:42 2021 GMT
                Not After : Dec 22 13:06:42 2024 GMT
            Subject: C = US, ST = , CN = monitoring.lab.
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    RSA Public-Key: (2048 bit)
                    Modulus:
    (...)
                    Exponent: 65537 (0x10001)
            X509v3 extensions:
                X509v3 Basic Constraints: 
                    CA:FALSE
                Netscape Cert Type: 
                    SSL Server
                Netscape Comment: 
                    OpenSSL Generated Server Certificate
                X509v3 Subject Key Identifier: 
                    (...)
                X509v3 Authority Key Identifier: 
                    keyid:(...)
                    DirName:/O= Lab Root CA/emailAddress=/L=/ST=/C=US/CN= Lab Root CA
                    serial:(...)
    
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Subject Alternative Name: 
                DNS:monitoring.lab.<domain>
    Signature Algorithm: sha256WithRSAEncryption
    

    (snip)



  • The error indicates that the root CA certificate is the cause, but your server certificate also looks "defect" as it's validity period is too long. Most web browsers do no accept validity periods longer than 13 months. The Subject Alternative Name extension is present so that should not cause problems (this extension is now mandatory).

    For the root CA cert I don't know what extension are really required I just compare it to the one created by Fiddler (which I know works):

    I see the following extensions:

    • X509v3 Basic Constraints (2.5.29.19):
      • CA: TRUE
      • Path Length Constraint: 0
    • KeyUsage (2.5.29.15)
      • Certificate Signing
    • SubjectKeyIdentifier (2.5.29.14)
      • 20 byte random identifier

    And of course the signature algorithm should be only secure algorithms like RSA with at least 2048bit key and SHA-256.




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2