1b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra/* 2b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * Copyright (C) 2012 The Android Open Source Project 3b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * 4b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * Licensed under the Apache License, Version 2.0 (the "License"); 5b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * you may not use this file except in compliance with the License. 6b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * You may obtain a copy of the License at 7b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * 8b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * http://www.apache.org/licenses/LICENSE-2.0 9b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * 10b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * Unless required by applicable law or agreed to in writing, software 11b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * distributed under the License is distributed on an "AS IS" BASIS, 12b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * See the License for the specific language governing permissions and 14b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * limitations under the License. 15b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra */ 16b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 17b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condrapackage com.android.server.updates; 18b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 193f72604be806c0173b5dca0225cadf6e7c872147Przemyslaw Szczepaniakimport com.android.internal.util.HexDump; 203f72604be806c0173b5dca0225cadf6e7c872147Przemyslaw Szczepaniak 21b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport android.content.Context; 22b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport android.content.Intent; 23b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport android.test.AndroidTestCase; 24b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport android.provider.Settings; 25b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport android.util.Base64; 26b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport android.util.Log; 27b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 28b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.io.ByteArrayInputStream; 29b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.io.File; 30b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.io.FileInputStream; 31b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.io.FileOutputStream; 32b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.io.FileWriter; 33b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.io.IOException; 34b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.io.InputStream; 35b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.cert.CertificateFactory; 36b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.cert.Certificate; 37b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.cert.X509Certificate; 38b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.MessageDigest; 39b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.NoSuchAlgorithmException; 40b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.PrivateKey; 41b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.Signature; 42b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.spec.PKCS8EncodedKeySpec; 43b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.security.KeyFactory; 44b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.util.HashSet; 45b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport java.io.*; 46b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condraimport libcore.io.IoUtils; 47b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 48b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra/** 49b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra * Tests for {@link com.android.server.CertPinInstallReceiver} 50b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra */ 51b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condrapublic class CertPinInstallReceiverTest extends AndroidTestCase { 52b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 53b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private static final String TAG = "CertPinInstallReceiverTest"; 54b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 55b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private static final String PINLIST_ROOT = System.getenv("ANDROID_DATA") + "/misc/keychain/"; 56b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 57b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public static final String PINLIST_CONTENT_PATH = PINLIST_ROOT + "pins"; 58b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public static final String PINLIST_METADATA_PATH = PINLIST_CONTENT_PATH + "metadata"; 59b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 60b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public static final String PINLIST_CONTENT_URL_KEY = "pinlist_content_url"; 61b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public static final String PINLIST_METADATA_URL_KEY = "pinlist_metadata_url"; 62b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public static final String PINLIST_CERTIFICATE_KEY = "config_update_certificate"; 63b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public static final String PINLIST_VERSION_KEY = "pinlist_version"; 64b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 65b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private static final String EXTRA_CONTENT_PATH = "CONTENT_PATH"; 66b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private static final String EXTRA_REQUIRED_HASH = "REQUIRED_HASH"; 67b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private static final String EXTRA_SIGNATURE = "SIGNATURE"; 68b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private static final String EXTRA_VERSION_NUMBER = "VERSION"; 69b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 70b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public static final String TEST_CERT = "" + 71b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "MIIDsjCCAxugAwIBAgIJAPLf2gS0zYGUMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYDVQQGEwJVUzET" + 72b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEPMA0GA1UEChMGR29v" + 73b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "Z2xlMRAwDgYDVQQLEwd0ZXN0aW5nMRYwFAYDVQQDEw1HZXJlbXkgQ29uZHJhMSEwHwYJKoZIhvcN" + 74b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "AQkBFhJnY29uZHJhQGdvb2dsZS5jb20wHhcNMTIwNzE0MTc1MjIxWhcNMTIwODEzMTc1MjIxWjCB" + 75b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "mDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZp" + 76b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "ZXcxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHdGVzdGluZzEWMBQGA1UEAxMNR2VyZW15IENv" + 77b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "bmRyYTEhMB8GCSqGSIb3DQEJARYSZ2NvbmRyYUBnb29nbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUA" + 78b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "A4GNADCBiQKBgQCjGGHATBYlmas+0sEECkno8LZ1KPglb/mfe6VpCT3GhSr+7br7NG/ZwGZnEhLq" + 79b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "E7YIH4fxltHmQC3Tz+jM1YN+kMaQgRRjo/LBCJdOKaMwUbkVynAH6OYsKevjrOPk8lfM5SFQzJMG" + 80b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "sA9+Tfopr5xg0BwZ1vA/+E3mE7Tr3M2UvwIDAQABo4IBADCB/TAdBgNVHQ4EFgQUhzkS9E6G+x8W" + 81b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "L4EsmRjDxu28tHUwgc0GA1UdIwSBxTCBwoAUhzkS9E6G+x8WL4EsmRjDxu28tHWhgZ6kgZswgZgx" + 82b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3" + 83b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "MQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB3Rlc3RpbmcxFjAUBgNVBAMTDUdlcmVteSBDb25k" + 84b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "cmExITAfBgkqhkiG9w0BCQEWEmdjb25kcmFAZ29vZ2xlLmNvbYIJAPLf2gS0zYGUMAwGA1UdEwQF" + 85b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAYiugFDmbDOQ2U/+mqNt7o8ftlEo9SJrns6O8uTtK6AvR" + 86b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "orDrR1AXTXkuxwLSbmVfedMGOZy7Awh7iZa8hw5x9XmUudfNxvmrKVEwGQY2DZ9PXbrnta/dwbhK" + 87b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "mWfoepESVbo7CKIhJp8gRW0h1Z55ETXD57aGJRvQS4pxkP8ANhM="; 88b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 89b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 90b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public static final String TEST_KEY = "" + 91b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKMYYcBMFiWZqz7SwQQKSejwtnUo" + 92b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "+CVv+Z97pWkJPcaFKv7tuvs0b9nAZmcSEuoTtggfh/GW0eZALdPP6MzVg36QxpCBFGOj8sEIl04p" + 93b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "ozBRuRXKcAfo5iwp6+Os4+TyV8zlIVDMkwawD35N+imvnGDQHBnW8D/4TeYTtOvczZS/AgMBAAEC" + 94b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "gYBxwFalNSwZK3WJipq+g6KLCiBn1JxGGDQlLKrweFaSuFyFky9fd3IvkIabirqQchD612sMb+GT" + 95b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "0t1jptW6z4w2w6++IW0A3apDOCwoD+uvDBXrbFqI0VbyAWUNqHVdaFFIRk2IHGEE6463mGRdmILX" + 96b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "IlCd/85RTHReg4rl/GFqWQJBANgLAIR4pWbl5Gm+DtY18wp6Q3pJAAMkmP/lISCBIidu1zcqYIKt" + 97b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "PoDW4Knq9xnhxPbXrXKv4YzZWHBK8GkKhQ0CQQDBQnXufQcMew+PwiS0oJvS+eQ6YJwynuqG2ejg" + 98b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "WE+T7489jKtscRATpUXpZUYmDLGg9bLt7L62hFvFSj2LO2X7AkBcdrD9AWnBFWlh/G77LVHczSEu" + 99b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "KCoyLiqxcs5vy/TjLaQ8vw1ZQG580/qJnr+tOxyCjSJ18GK3VppsTRaBznfNAkB3nuCKNp9HTWCL" + 100b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "dfrsRsFMrFpk++mSt6SoxXaMbn0LL2u1CD4PCEiQMGt+lK3/3TmRTKNs+23sYS7Ahjxj0udDAkEA" + 101b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "p57Nj65WNaWeYiOfTwKXkLj8l29H5NbaGWxPT0XkWr4PvBOFZVH/wj0/qc3CMVGnv11+DyO+QUCN" + 102b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra "SqBB5aRe8g=="; 103b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 104b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private void overrideSettings(String key, String value) throws Exception { 105b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra assertTrue(Settings.Secure.putString(mContext.getContentResolver(), key, value)); 106b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Thread.sleep(1000); 107b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 108b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 109b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private void overrideCert(String value) throws Exception { 110b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra overrideSettings(PINLIST_CERTIFICATE_KEY, value); 111b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 112b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 113b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private String readPins() throws Exception { 114b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return IoUtils.readFileAsString(PINLIST_CONTENT_PATH); 115b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 116b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 117b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private String readCurrentVersion() throws Exception { 118b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return IoUtils.readFileAsString("/data/misc/keychain/metadata/version"); 119b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 120b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 121b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private String getNextVersion() throws Exception { 122b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra int currentVersion = Integer.parseInt(readCurrentVersion()); 123b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return Integer.toString(currentVersion + 1); 124b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 125b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 126b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private static String getCurrentHash(String content) throws Exception { 127b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra if (content == null) { 128b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return "0"; 129b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 130b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra MessageDigest dgst = MessageDigest.getInstance("SHA512"); 131b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra byte[] encoded = content.getBytes(); 132b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra byte[] fingerprint = dgst.digest(encoded); 1333f72604be806c0173b5dca0225cadf6e7c872147Przemyslaw Szczepaniak return HexDump.toHexString(fingerprint, false); 134b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 135b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 136b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private static String getHashOfCurrentContent() throws Exception { 137b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra String content = IoUtils.readFileAsString("/data/misc/keychain/pins"); 138b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return getCurrentHash(content); 139b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 140b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 141b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private PrivateKey createKey() throws Exception { 142b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra byte[] derKey = Base64.decode(TEST_KEY.getBytes(), Base64.DEFAULT); 143b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(derKey); 144b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 145b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return (PrivateKey) keyFactory.generatePrivate(keySpec); 146b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 147b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 148b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private X509Certificate createCertificate() throws Exception { 149b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra byte[] derCert = Base64.decode(TEST_CERT.getBytes(), Base64.DEFAULT); 150b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra InputStream istream = new ByteArrayInputStream(derCert); 151b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra CertificateFactory cf = CertificateFactory.getInstance("X.509"); 152b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return (X509Certificate) cf.generateCertificate(istream); 153b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 154b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 155b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private String makeTemporaryContentFile(String content) throws Exception { 156b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra FileOutputStream fw = mContext.openFileOutput("content.txt", mContext.MODE_WORLD_READABLE); 157b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra fw.write(content.getBytes(), 0, content.length()); 158b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra fw.close(); 159b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return mContext.getFilesDir() + "/content.txt"; 160b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 161b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 162b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private String createSignature(String content, String version, String requiredHash) 163b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra throws Exception { 164b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Signature signer = Signature.getInstance("SHA512withRSA"); 165b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra signer.initSign(createKey()); 166b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra signer.update(content.trim().getBytes()); 167b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra signer.update(version.trim().getBytes()); 168b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra signer.update(requiredHash.getBytes()); 169b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra String sig = new String(Base64.encode(signer.sign(), Base64.DEFAULT)); 170b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra assertEquals(true, 171b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra verifySignature(content, version, requiredHash, sig, createCertificate())); 172b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return sig; 173b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 174b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 175b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public boolean verifySignature(String content, String version, String requiredPrevious, 176b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra String signature, X509Certificate cert) throws Exception { 177b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Signature signer = Signature.getInstance("SHA512withRSA"); 178b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra signer.initVerify(cert); 179b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra signer.update(content.trim().getBytes()); 180b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra signer.update(version.trim().getBytes()); 181b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra signer.update(requiredPrevious.trim().getBytes()); 182b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return signer.verify(Base64.decode(signature.getBytes(), Base64.DEFAULT)); 183b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 184b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 185b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private void sendIntent(String contentPath, String version, String required, String sig) { 186b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Intent i = new Intent(); 187b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra i.setAction("android.intent.action.UPDATE_PINS"); 188b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra i.putExtra(EXTRA_CONTENT_PATH, contentPath); 189b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra i.putExtra(EXTRA_VERSION_NUMBER, version); 190b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra i.putExtra(EXTRA_REQUIRED_HASH, required); 191b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra i.putExtra(EXTRA_SIGNATURE, sig); 192b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra mContext.sendBroadcast(i); 193b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 194b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 195b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private String runTest(String cert, String content, String version, String required, String sig) 196b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra throws Exception { 197b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Log.e(TAG, "started test"); 198b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra overrideCert(cert); 199b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra String contentPath = makeTemporaryContentFile(content); 200b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra sendIntent(contentPath, version, required, sig); 201b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Thread.sleep(1000); 202b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return readPins(); 203b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 204b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 205b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra private String runTestWithoutSig(String cert, String content, String version, String required) 206b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra throws Exception { 207b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra String sig = createSignature(content, version, required); 208b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra return runTest(cert, content, version, required, sig); 209b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 210b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 211b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public void testOverwritePinlist() throws Exception { 212b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Log.e(TAG, "started testOverwritePinList"); 213b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra assertEquals("abcde", runTestWithoutSig(TEST_CERT, "abcde", getNextVersion(), getHashOfCurrentContent())); 214b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Log.e(TAG, "started testOverwritePinList"); 215b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 216b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 217b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public void testBadSignatureFails() throws Exception { 218b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Log.e(TAG, "started testOverwritePinList"); 219b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra String text = "blahblah"; 220b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra runTestWithoutSig(TEST_CERT, text, getNextVersion(), getHashOfCurrentContent()); 221b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra assertEquals(text, runTest(TEST_CERT, "bcdef", getNextVersion(), getCurrentHash(text), "")); 222b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Log.e(TAG, "started testOverwritePinList"); 223b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 224b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 225b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public void testBadRequiredHashFails() throws Exception { 226b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra runTestWithoutSig(TEST_CERT, "blahblahblah", getNextVersion(), getHashOfCurrentContent()); 227b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra assertEquals("blahblahblah", runTestWithoutSig(TEST_CERT, "cdefg", getNextVersion(), "0")); 228b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Log.e(TAG, "started testOverwritePinList"); 229b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 230b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 231b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public void testBadVersionFails() throws Exception { 232b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra String text = "blahblahblahblah"; 233b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra String version = getNextVersion(); 234b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra runTestWithoutSig(TEST_CERT, text, version, getHashOfCurrentContent()); 235b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra assertEquals(text, runTestWithoutSig(TEST_CERT, "defgh", version, getCurrentHash(text))); 236b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Log.e(TAG, "started testOverwritePinList"); 237b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 238b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 239b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra public void testOverrideRequiredHash() throws Exception { 240b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra runTestWithoutSig(TEST_CERT, "blahblahblah", getNextVersion(), getHashOfCurrentContent()); 241b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra assertEquals("blahblahblah", runTestWithoutSig(TEST_CERT, "cdefg", "NONE", "0")); 242b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra Log.e(TAG, "started testOverwritePinList"); 243b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra } 244b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra 245b631084613e12e1c6a0ae2ad9446e1284b650ccbGeremy Condra} 246