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