1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.security.keystore.recovery; 18 19 import static android.security.keystore.recovery.X509CertificateParsingUtils.decodeBase64Cert; 20 21 import android.annotation.NonNull; 22 import android.util.ArrayMap; 23 24 import java.security.cert.CertificateException; 25 import java.security.cert.X509Certificate; 26 import java.util.Map; 27 28 /** 29 * Trusted root certificates for use by the 30 * {@link android.security.keystore.recovery.RecoveryController}. These certificates are used to 31 * verify the public keys of remote secure hardware modules. This is to prevent AOSP backing up keys 32 * to untrusted devices. 33 * 34 * @hide 35 */ 36 public final class TrustedRootCertificates { 37 38 public static final String GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS = 39 "GoogleCloudKeyVaultServiceV1"; 40 /** 41 * Certificate used for client-side end-to-end encryption tests. 42 * When recovery controller is initialized with the certificate, recovery snapshots will only 43 * contain application keys started with {@link #INSECURE_KEY_ALIAS_PREFIX}. 44 * Recovery snapshot will only be created if device is unlocked with password started with 45 * {@link #INSECURE_PASSWORD_PREFIX}. 46 * 47 * @hide 48 */ 49 public static final String TEST_ONLY_INSECURE_CERTIFICATE_ALIAS = 50 "TEST_ONLY_INSECURE_CERTIFICATE_ALIAS"; 51 52 /** 53 * TODO: Add insecure certificate to TestApi. 54 * @hide 55 */ getTestOnlyInsecureCertificate()56 public static @NonNull X509Certificate getTestOnlyInsecureCertificate() { 57 return parseBase64Certificate(TEST_ONLY_INSECURE_CERTIFICATE_BASE64); 58 } 59 /** 60 * Keys, which alias starts with the prefix are not protected if 61 * recovery agent uses {@link #TEST_ONLY_INSECURE_CERTIFICATE_ALIAS} root certificate. 62 * @hide 63 */ 64 public static final String INSECURE_KEY_ALIAS_PREFIX = 65 "INSECURE_KEY_ALIAS_KEY_MATERIAL_IS_NOT_PROTECTED_"; 66 /** 67 * Prefix for insecure passwords with length 14. 68 * Passwords started with the prefix are not protected if recovery agent uses 69 * {@link #TEST_ONLY_INSECURE_CERTIFICATE_ALIAS} root certificate. 70 * @hide 71 */ 72 public static final String INSECURE_PASSWORD_PREFIX = 73 "INSECURE_PSWD_"; 74 75 private static final String GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_BASE64 = "" 76 + "MIIFDzCCAvegAwIBAgIQbNdueU2o0vM9gGq4N6bhjzANBgkqhkiG9w0BAQsFADAx" 77 + "MS8wLQYDVQQDEyZHb29nbGUgQ2xvdWQgS2V5IFZhdWx0IFNlcnZpY2UgUm9vdCBD" 78 + "QTAeFw0xODA1MDcxODI0MDJaFw0zODA1MDgxOTI0MDJaMDExLzAtBgNVBAMTJkdv" 79 + "b2dsZSBDbG91ZCBLZXkgVmF1bHQgU2VydmljZSBSb290IENBMIICIjANBgkqhkiG" 80 + "9w0BAQEFAAOCAg8AMIICCgKCAgEArUgzu+4o9yl22eql1BiGBq3gWXooh2ql3J+v" 81 + "Vuzf/ThjzdIg0xkkkw/NAFxYFi49Eo1fa/hf8wCIoAqCEs1lD6tE3cCD3T3+EQPq" 82 + "uh6CB2KmZDJ6mPnXvVUlUuFr0O2MwZkwylqBETzK0x5NCHgL/p47vkjhHx6LqVao" 83 + "bigKlHxszvVi4fkt/qq7KW3YTVxhwdLGEab+OqSfwMxdBLhMfE0K0dvFt8bs8yJA" 84 + "F04DJsMbRChFFBpT17Z0u53iIAAu5qVQhKrQXiIAwgboZqd+JkHLXU1fJeVT5WJO" 85 + "JgoJFWHkdWkHta4mSYlS72J1Q927JD1JdET1kFtH+EDtYAtx7x7F9xAAbb2tMITw" 86 + "s/wwd2rAzZTX/kxRbDlXVLToU05LFYPr+dFV1wvXmi0jlkIxnhdaVBqWC93p528U" 87 + "iUcLpib+HVzMWGdYI3G1NOa/lTp0c8LcbJjapiiVneRQJ3cIqDPOSEnEq40hyZd1" 88 + "jx3JnOxJMwHs8v4s9GIlb3BcOmDvA/Mu09xEMKwpHBm4TFDKXeGHOWha7ccWEECb" 89 + "yO5ncu6XuN2iyz9S+TuMyjZBE552p6Pu5gEC2xk+qab0NGDTHdLKLbyWn3IxdmBH" 90 + "yTr7iPCqmpyHngkC/pbGfvGusc5BpBugsBtlz67m4RWLJ72yAeVPO/ly/8w4orNs" 91 + "GWjn3s0CAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w" 92 + "DQYJKoZIhvcNAQELBQADggIBAGiWlu+4qyxgPb6RsA0mwR7V21UJ9rEpYhSN+ARp" 93 + "TWGiI22RCJSGK0ZrPGeFQzE2BpnVRdmLTV5jf9JUStjHoPvNYFnwLTJ0E2e9Olj8" 94 + "MrHrAucAUFLhl4woWz0kU/X0EB1j6Y2SXrAaZPiMMpq8BKj3mH1MbV4stZ0kiHUp" 95 + "Zu6PEmrojYG7FKKN30na2xXfiOfl2JusVsyHDqmUn/HjTh6zASKqE6hxE+FJRl2V" 96 + "Q4dcr4SviHtdbimMy2LghLnZ4FE4XhJgRnw9TeRV5C9Sn7pmnAA5X0C8ZXhXvfvr" 97 + "dx4fL3UKlk1Lqlb5skxoK1R9wwr+aNIO+cuR8JA5DmEDWFw5Budh/uWWZlBTyVW2" 98 + "ybbTB6tkmOc8c08XOgxBaKrsXALmJcluabjmN1jp81ae1epeN31jJ4N5IE5aq7Xb" 99 + "TFmKkwpgTTvJmqCR2XzWujlvdbdjfiABliWsnLzLQCP8eZwcM4LA5UK3f1ktHolr" 100 + "1OI9etSOkebE2py8LPYBJWlX36tRAagZhU/NoyOtvhRzq9rb3rbf96APEHKUFsXG" 101 + "9nBEd2BUKZghLKPf+JNCU/2pOGx0jdMcf+K+a1DeG0YzGYMRkFvpN3hvHYrJdByL" 102 + "3kSP3UtD0H2g8Ps7gRLELG2HODxbSn8PV3XtuSvxVanA6uyaaS3AZ6SxeVLvmw50" 103 + "7aYI"; 104 105 private static final String TEST_ONLY_INSECURE_CERTIFICATE_BASE64 = "" 106 + "MIIFMDCCAxigAwIBAgIJAIZ9/G8KQie9MA0GCSqGSIb3DQEBDQUAMCUxIzAhBgNV" 107 + "BAMMGlRlc3QgT25seSBVbnNlY3VyZSBSb290IENBMB4XDTE4MDMyODAwMzIyM1oX" 108 + "DTM4MDMyMzAwMzIyM1owJTEjMCEGA1UEAwwaVGVzdCBPbmx5IFVuc2VjdXJlIFJv" 109 + "b3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGxFNzAEyzSPmw" 110 + "E5gfuBXdXq++bl9Ep62V7Xn1UiejvmS+pRHT39pf/M7sl4Zr9ezanJTrFvf9+B85" 111 + "VGehdsD32TgfEjThcqaoQCI6pKkHYsUo7FZ5n+G3eE8oabWRZJMVo3QDjnnFYp7z" 112 + "20vnpjDofI2oQyxHcb/1yep+ca1+4lIvbUp/ybhNFqhRXAMcDXo7pyH38eUQ1JdK" 113 + "Q/QlBbShpFEqx1Y6KilKfTDf7Wenqr67LkaEim//yLZjlHzn/BpuRTrpo+XmJZx1" 114 + "P9CX9LGOXTtmsaCcYgD4yijOvV8aEsIJaf1kCIO558oH0oQc+0JG5aXeLN7BDlyZ" 115 + "vH0RdSx5nQLS9kj2I6nthOw/q00/L+S6A0m5jyNZOAl1SY78p+wO0d9eHbqQzJwf" 116 + "EsSq3qGAqlgQyyjp6oxHBqT9hZtN4rxw+iq0K1S4kmTLNF1FvmIB1BE+lNvvoGdY" 117 + "5G0b6Pe4R5JFn9LV3C3PEmSYnae7iG0IQlKmRADIuvfJ7apWAVanJPJAAWh2Akfp" 118 + "8Uxr02cHoY6o7vsEhJJOeMkipaBHThESm/XeFVubQzNfZ9gjQnB9ZX2v+lyj+WYZ" 119 + "SAz3RuXx6TlLrmWccMpQDR1ibcgyyjLUtX3kwZl2OxmJXitjuD7xlxvAXYob15N+" 120 + "K4xKHgxUDrbt2zU/tY0vgepAUg/xbwIDAQABo2MwYTAdBgNVHQ4EFgQUwyeNpYgs" 121 + "XXYvh9z0/lFrja7sV+swHwYDVR0jBBgwFoAUwyeNpYgsXXYvh9z0/lFrja7sV+sw" 122 + "DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQENBQAD" 123 + "ggIBAGuOsvMN5SD3RIQnMJtBpcHNrxun+QFjPZFlYCLfIPrUkHpn5O1iIIq8tVLd" 124 + "2V+12VKnToUEANsYBD3MP8XjP+6GZ7ZQ2rwLGvUABKSX4YXvmjEEXZUZp0y3tIV4" 125 + "kUDlbACzguPneZDp5Qo7YWH4orgqzHkn0sD/ikO5XrAqmzc245ewJlrf+V11mjcu" 126 + "ELfDrEejpPhi7Hk/ZNR0ftP737Hs/dNoCLCIaVNgYzBZhgo4kd220TeJu2ttW0XZ" 127 + "ldyShtpcOmyWKBgVseixR6L/3sspPHyAPXkSuRo0Eh1xvzDKCg9ttb0qoacTlXMF" 128 + "GkBpNzmVq67NWFGGa9UElift1mv6RfktPCAGZ+Ai8xUiKAUB0Eookpt/8gX9Senq" 129 + "yP/jMxkxXmHWxUu8+KnLvj6WLrfftuuD7u3cfc7j5kkrheDz3O4h4477GnqL5wdo" 130 + "9DuEsNc4FxJVz8Iy8RS6cJuW4pihYpM1Tyn7uopLnImpYzEY+R5aQqqr+q/A1diq" 131 + "ogbEKPH6oUiqJUwq3nD70gPBUKJmIzS4vLwLouqUHEm1k/MgHV/BkEU0uVHszPFa" 132 + "XUMMCHb0iT9P8LuZ7Ajer3SR/0TRVApCrk/6OV68e+6k/OFpM5kcZnNMD5ANyBri" 133 + "Tsz3NrDwSw4i4+Dsfh6A9dB/cEghw4skLaBxnQLQIgVeqCzK"; 134 135 /** 136 * The X509 certificate of the trusted root CA cert for the recoverable key store service. 137 */ 138 private static final X509Certificate GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_CERTIFICATE = 139 parseBase64Certificate(GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_BASE64); 140 141 private static final int NUMBER_OF_ROOT_CERTIFICATES = 1; 142 143 private static final ArrayMap<String, X509Certificate> ALL_ROOT_CERTIFICATES = 144 constructRootCertificateMap(); 145 146 /** 147 * Returns all available root certificates, keyed by alias. 148 */ getRootCertificates()149 public static @NonNull Map<String, X509Certificate> getRootCertificates() { 150 return new ArrayMap(ALL_ROOT_CERTIFICATES); 151 } 152 153 /** 154 * Gets a root certificate referenced by the given {@code alias}. 155 * 156 * @param alias the alias of the certificate 157 * @return the certificate referenced by the alias, or null if such a certificate doesn't exist. 158 */ getRootCertificate(String alias)159 public static @NonNull X509Certificate getRootCertificate(String alias) { 160 return ALL_ROOT_CERTIFICATES.get(alias); 161 } 162 constructRootCertificateMap()163 private static ArrayMap<String, X509Certificate> constructRootCertificateMap() { 164 ArrayMap<String, X509Certificate> certificates = 165 new ArrayMap<>(NUMBER_OF_ROOT_CERTIFICATES); 166 certificates.put( 167 GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS, 168 GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_CERTIFICATE); 169 return certificates; 170 } 171 parseBase64Certificate(String base64Certificate)172 private static X509Certificate parseBase64Certificate(String base64Certificate) { 173 try { 174 return decodeBase64Cert(base64Certificate); 175 } catch (CertificateException e) { 176 // Should not happen 177 throw new RuntimeException(e); 178 } 179 } 180 181 // Statics only TrustedRootCertificates()182 private TrustedRootCertificates() {} 183 } 184