1/*
2 * Copyright (C) 2012 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
17package android.security;
18
19import android.test.AndroidTestCase;
20
21import java.io.ByteArrayInputStream;
22import java.math.BigInteger;
23import java.security.KeyPair;
24import java.security.PrivateKey;
25import java.security.PublicKey;
26import java.security.SecureRandom;
27import java.security.cert.Certificate;
28import java.security.cert.CertificateFactory;
29import java.security.cert.X509Certificate;
30import java.security.interfaces.DSAParams;
31import java.security.interfaces.DSAPublicKey;
32import java.security.interfaces.ECPublicKey;
33import java.security.interfaces.RSAPublicKey;
34import java.security.spec.AlgorithmParameterSpec;
35import java.security.spec.DSAParameterSpec;
36import java.security.spec.RSAKeyGenParameterSpec;
37import java.text.SimpleDateFormat;
38import java.util.Date;
39
40import javax.security.auth.x500.X500Principal;
41
42public class AndroidKeyPairGeneratorTest extends AndroidTestCase {
43    private android.security.KeyStore mAndroidKeyStore;
44
45    private java.security.KeyPairGenerator mGenerator;
46
47    private static final String TEST_ALIAS_1 = "test1";
48
49    private static final String TEST_ALIAS_2 = "test2";
50
51    private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
52
53    private static final X500Principal TEST_DN_2 = new X500Principal("CN=test2");
54
55    private static final BigInteger TEST_SERIAL_1 = BigInteger.ONE;
56
57    private static final BigInteger TEST_SERIAL_2 = BigInteger.valueOf(2L);
58
59    private static final long NOW_MILLIS = System.currentTimeMillis();
60
61    /* We have to round this off because X509v3 doesn't store milliseconds. */
62    private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L));
63
64    @SuppressWarnings("deprecation")
65    private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1);
66
67    @Override
68    protected void setUp() throws Exception {
69        mAndroidKeyStore = android.security.KeyStore.getInstance();
70
71        assertTrue(mAndroidKeyStore.reset());
72
73        assertFalse(mAndroidKeyStore.isUnlocked());
74
75        mGenerator = java.security.KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
76    }
77
78    private void setupPassword() {
79        assertTrue(mAndroidKeyStore.password("1111"));
80        assertTrue(mAndroidKeyStore.isUnlocked());
81
82        String[] aliases = mAndroidKeyStore.saw("");
83        assertNotNull(aliases);
84        assertEquals(0, aliases.length);
85    }
86
87    public void testKeyPairGenerator_Initialize_Params_Encrypted_Success() throws Exception {
88        setupPassword();
89
90        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
91                .setAlias(TEST_ALIAS_1)
92                .setSubject(TEST_DN_1)
93                .setSerialNumber(TEST_SERIAL_1)
94                .setStartDate(NOW)
95                .setEndDate(NOW_PLUS_10_YEARS)
96                .setEncryptionRequired()
97                .build());
98    }
99
100    public void testKeyPairGenerator_Initialize_KeySize_Encrypted_Failure() throws Exception {
101        setupPassword();
102
103        try {
104            mGenerator.initialize(1024);
105            fail("KeyPairGenerator should not support setting the key size");
106        } catch (IllegalArgumentException success) {
107        }
108    }
109
110    public void testKeyPairGenerator_Initialize_KeySizeAndSecureRandom_Encrypted_Failure()
111            throws Exception {
112        setupPassword();
113
114        try {
115            mGenerator.initialize(1024, new SecureRandom());
116            fail("KeyPairGenerator should not support setting the key size");
117        } catch (IllegalArgumentException success) {
118        }
119    }
120
121    public void testKeyPairGenerator_Initialize_ParamsAndSecureRandom_Encrypted_Failure()
122            throws Exception {
123        setupPassword();
124
125        mGenerator.initialize(
126                new KeyPairGeneratorSpec.Builder(getContext())
127                        .setAlias(TEST_ALIAS_1)
128                        .setKeyType("RSA")
129                        .setKeySize(1024)
130                        .setSubject(TEST_DN_1)
131                        .setSerialNumber(TEST_SERIAL_1)
132                        .setStartDate(NOW)
133                        .setEndDate(NOW_PLUS_10_YEARS)
134                        .setEncryptionRequired()
135                        .build(),
136                new SecureRandom());
137    }
138
139    public void testKeyPairGenerator_GenerateKeyPair_Encrypted_Success() throws Exception {
140        setupPassword();
141
142        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
143                .setAlias(TEST_ALIAS_1)
144                .setSubject(TEST_DN_1)
145                .setSerialNumber(TEST_SERIAL_1)
146                .setStartDate(NOW)
147                .setEndDate(NOW_PLUS_10_YEARS)
148                .setEncryptionRequired()
149                .build());
150
151        final KeyPair pair = mGenerator.generateKeyPair();
152        assertNotNull("The KeyPair returned should not be null", pair);
153
154        assertKeyPairCorrect(pair, TEST_ALIAS_1, "RSA", 2048, null, TEST_DN_1, TEST_SERIAL_1, NOW,
155                NOW_PLUS_10_YEARS);
156    }
157
158    public void testKeyPairGenerator_GenerateKeyPair_DSA_Unencrypted_Success() throws Exception {
159        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
160                .setAlias(TEST_ALIAS_1)
161                .setKeyType("DSA")
162                .setSubject(TEST_DN_1)
163                .setSerialNumber(TEST_SERIAL_1)
164                .setStartDate(NOW)
165                .setEndDate(NOW_PLUS_10_YEARS)
166                .build());
167
168        final KeyPair pair = mGenerator.generateKeyPair();
169        assertNotNull("The KeyPair returned should not be null", pair);
170
171        assertKeyPairCorrect(pair, TEST_ALIAS_1, "DSA", 1024, null, TEST_DN_1, TEST_SERIAL_1, NOW,
172                NOW_PLUS_10_YEARS);
173    }
174
175    public void testKeyPairGenerator_GenerateKeyPair_DSA_2048_Unencrypted_Success()
176            throws Exception {
177        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
178                .setAlias(TEST_ALIAS_1)
179                .setKeyType("DSA")
180                .setKeySize(2048)
181                .setSubject(TEST_DN_1)
182                .setSerialNumber(TEST_SERIAL_1)
183                .setStartDate(NOW)
184                .setEndDate(NOW_PLUS_10_YEARS)
185                .build());
186
187        final KeyPair pair = mGenerator.generateKeyPair();
188        assertNotNull("The KeyPair returned should not be null", pair);
189
190        assertKeyPairCorrect(pair, TEST_ALIAS_1, "DSA", 2048, null, TEST_DN_1, TEST_SERIAL_1, NOW,
191                NOW_PLUS_10_YEARS);
192    }
193
194    public void testKeyPairGenerator_GenerateKeyPair_DSA_SpecifiedParams_Unencrypted_Success()
195            throws Exception {
196        /*
197         * generated using: openssl dsaparam -C 2048
198         */
199        BigInteger p = new BigInteger(1, new byte[] {
200                (byte) 0xC0, (byte) 0x3D, (byte) 0x86, (byte) 0x09, (byte) 0xCA, (byte) 0x8C,
201                (byte) 0x37, (byte) 0xCA, (byte) 0xCC, (byte) 0x4A, (byte) 0x81, (byte) 0xBD,
202                (byte) 0xD8, (byte) 0x50, (byte) 0x77, (byte) 0xCD, (byte) 0xDD, (byte) 0x32,
203                (byte) 0x0B, (byte) 0x43, (byte) 0xBF, (byte) 0x42, (byte) 0x06, (byte) 0x5A,
204                (byte) 0x3D, (byte) 0x18, (byte) 0x50, (byte) 0x47, (byte) 0x79, (byte) 0xE1,
205                (byte) 0x5B, (byte) 0x86, (byte) 0x03, (byte) 0xB9, (byte) 0x28, (byte) 0x9C,
206                (byte) 0x18, (byte) 0xA9, (byte) 0xF5, (byte) 0xD6, (byte) 0xF4, (byte) 0x94,
207                (byte) 0x5B, (byte) 0x87, (byte) 0x58, (byte) 0xCA, (byte) 0xB2, (byte) 0x1E,
208                (byte) 0xFC, (byte) 0xED, (byte) 0x37, (byte) 0xC3, (byte) 0x49, (byte) 0xAC,
209                (byte) 0xFA, (byte) 0x46, (byte) 0xDB, (byte) 0x7A, (byte) 0x50, (byte) 0x96,
210                (byte) 0xCF, (byte) 0x52, (byte) 0xD7, (byte) 0x4E, (byte) 0xEB, (byte) 0x26,
211                (byte) 0x41, (byte) 0xA2, (byte) 0x6F, (byte) 0x99, (byte) 0x80, (byte) 0x9F,
212                (byte) 0x0F, (byte) 0x0A, (byte) 0xA8, (byte) 0x0D, (byte) 0xAC, (byte) 0xAB,
213                (byte) 0xEF, (byte) 0x7D, (byte) 0xE7, (byte) 0x4C, (byte) 0xF1, (byte) 0x88,
214                (byte) 0x44, (byte) 0xC9, (byte) 0x17, (byte) 0xD0, (byte) 0xBB, (byte) 0xE2,
215                (byte) 0x01, (byte) 0x8C, (byte) 0xC1, (byte) 0x02, (byte) 0x1D, (byte) 0x3C,
216                (byte) 0x15, (byte) 0xB7, (byte) 0x41, (byte) 0x30, (byte) 0xD8, (byte) 0x11,
217                (byte) 0xBD, (byte) 0x6A, (byte) 0x2A, (byte) 0x0D, (byte) 0x36, (byte) 0x44,
218                (byte) 0x9C, (byte) 0x3F, (byte) 0x32, (byte) 0xE2, (byte) 0x1C, (byte) 0xFB,
219                (byte) 0xE3, (byte) 0xFF, (byte) 0xCC, (byte) 0x1A, (byte) 0x72, (byte) 0x38,
220                (byte) 0x37, (byte) 0x69, (byte) 0x5E, (byte) 0x35, (byte) 0x73, (byte) 0xE1,
221                (byte) 0x1E, (byte) 0x74, (byte) 0x35, (byte) 0x44, (byte) 0x07, (byte) 0xB5,
222                (byte) 0x2F, (byte) 0x0B, (byte) 0x60, (byte) 0xF4, (byte) 0xA9, (byte) 0xE0,
223                (byte) 0x81, (byte) 0xB2, (byte) 0xCD, (byte) 0x8B, (byte) 0x82, (byte) 0x76,
224                (byte) 0x7F, (byte) 0xD4, (byte) 0x17, (byte) 0x32, (byte) 0x86, (byte) 0x98,
225                (byte) 0x7C, (byte) 0x85, (byte) 0x66, (byte) 0xF6, (byte) 0x77, (byte) 0xED,
226                (byte) 0x8B, (byte) 0x1A, (byte) 0x52, (byte) 0x16, (byte) 0xDA, (byte) 0x1C,
227                (byte) 0xA7, (byte) 0x16, (byte) 0x79, (byte) 0x20, (byte) 0x1C, (byte) 0x99,
228                (byte) 0x5F, (byte) 0x12, (byte) 0x66, (byte) 0x15, (byte) 0x9F, (byte) 0xE5,
229                (byte) 0x73, (byte) 0xA9, (byte) 0x61, (byte) 0xBA, (byte) 0xA7, (byte) 0x23,
230                (byte) 0x93, (byte) 0x77, (byte) 0xB5, (byte) 0xF6, (byte) 0xEC, (byte) 0x13,
231                (byte) 0xBF, (byte) 0x95, (byte) 0x60, (byte) 0x78, (byte) 0x84, (byte) 0xE3,
232                (byte) 0x44, (byte) 0xEC, (byte) 0x74, (byte) 0xC2, (byte) 0xCB, (byte) 0xD4,
233                (byte) 0x70, (byte) 0xC5, (byte) 0x7B, (byte) 0xF8, (byte) 0x07, (byte) 0x3B,
234                (byte) 0xEB, (byte) 0x9F, (byte) 0xC9, (byte) 0x7D, (byte) 0xE0, (byte) 0xA5,
235                (byte) 0xBA, (byte) 0x68, (byte) 0x7B, (byte) 0xF4, (byte) 0x70, (byte) 0x40,
236                (byte) 0xAE, (byte) 0xE9, (byte) 0x65, (byte) 0xEE, (byte) 0x5B, (byte) 0x71,
237                (byte) 0x36, (byte) 0x0B, (byte) 0xB0, (byte) 0xA2, (byte) 0x98, (byte) 0x7D,
238                (byte) 0xE3, (byte) 0x24, (byte) 0x95, (byte) 0x2B, (byte) 0xC2, (byte) 0x0A,
239                (byte) 0x78, (byte) 0x3D, (byte) 0xCC, (byte) 0x3A, (byte) 0xEE, (byte) 0xED,
240                (byte) 0x48, (byte) 0xEB, (byte) 0xA3, (byte) 0x78, (byte) 0xA8, (byte) 0x9D,
241                (byte) 0x0A, (byte) 0x8F, (byte) 0x9E, (byte) 0x59, (byte) 0x2C, (byte) 0x44,
242                (byte) 0xB5, (byte) 0xF9, (byte) 0x53, (byte) 0x43,
243        });
244
245        BigInteger q = new BigInteger(1, new byte[] {
246                (byte) 0xA1, (byte) 0x9B, (byte) 0x1D, (byte) 0xC0, (byte) 0xE3, (byte) 0xF6,
247                (byte) 0x4A, (byte) 0x35, (byte) 0xE1, (byte) 0x8A, (byte) 0x43, (byte) 0xC2,
248                (byte) 0x9C, (byte) 0xF9, (byte) 0x52, (byte) 0x8F, (byte) 0x94, (byte) 0xA1,
249                (byte) 0x12, (byte) 0x11, (byte) 0xDB, (byte) 0x9A, (byte) 0xB6, (byte) 0x35,
250                (byte) 0x56, (byte) 0x26, (byte) 0x60, (byte) 0x89, (byte) 0x11, (byte) 0xAC,
251                (byte) 0xA8, (byte) 0xE5,
252        });
253
254        BigInteger g = new BigInteger(1, new byte[] {
255                (byte) 0xA1, (byte) 0x5C, (byte) 0x57, (byte) 0x15, (byte) 0xC3, (byte) 0xD9,
256                (byte) 0xD7, (byte) 0x41, (byte) 0x89, (byte) 0xD6, (byte) 0xB8, (byte) 0x7B,
257                (byte) 0xF3, (byte) 0xE0, (byte) 0xB3, (byte) 0xC5, (byte) 0xD1, (byte) 0xAA,
258                (byte) 0xF9, (byte) 0x55, (byte) 0x48, (byte) 0xF1, (byte) 0xDA, (byte) 0xE8,
259                (byte) 0x6F, (byte) 0x51, (byte) 0x05, (byte) 0xB2, (byte) 0xC9, (byte) 0x64,
260                (byte) 0xDA, (byte) 0x5F, (byte) 0xD4, (byte) 0xAA, (byte) 0xFD, (byte) 0x67,
261                (byte) 0xE0, (byte) 0x10, (byte) 0x2C, (byte) 0x1F, (byte) 0x03, (byte) 0x10,
262                (byte) 0xD4, (byte) 0x4B, (byte) 0x20, (byte) 0x82, (byte) 0x2B, (byte) 0x04,
263                (byte) 0xF9, (byte) 0x09, (byte) 0xAE, (byte) 0x28, (byte) 0x3D, (byte) 0x9B,
264                (byte) 0xFF, (byte) 0x87, (byte) 0x76, (byte) 0xCD, (byte) 0xF0, (byte) 0x11,
265                (byte) 0xB7, (byte) 0xEA, (byte) 0xE6, (byte) 0xCD, (byte) 0x60, (byte) 0xD3,
266                (byte) 0x8C, (byte) 0x74, (byte) 0xD3, (byte) 0x45, (byte) 0x63, (byte) 0x69,
267                (byte) 0x3F, (byte) 0x1D, (byte) 0x31, (byte) 0x25, (byte) 0x49, (byte) 0x97,
268                (byte) 0x4B, (byte) 0x73, (byte) 0x34, (byte) 0x12, (byte) 0x73, (byte) 0x27,
269                (byte) 0x4C, (byte) 0xDA, (byte) 0xF3, (byte) 0x08, (byte) 0xA8, (byte) 0xA9,
270                (byte) 0x27, (byte) 0xE4, (byte) 0xB8, (byte) 0xD6, (byte) 0xB5, (byte) 0xC4,
271                (byte) 0x18, (byte) 0xED, (byte) 0xBD, (byte) 0x6F, (byte) 0xA2, (byte) 0x36,
272                (byte) 0xA2, (byte) 0x9C, (byte) 0x27, (byte) 0x62, (byte) 0x7F, (byte) 0x93,
273                (byte) 0xD7, (byte) 0x52, (byte) 0xA9, (byte) 0x76, (byte) 0x55, (byte) 0x99,
274                (byte) 0x00, (byte) 0x5B, (byte) 0xC2, (byte) 0xB9, (byte) 0x18, (byte) 0xAC,
275                (byte) 0x6B, (byte) 0x83, (byte) 0x0D, (byte) 0xA1, (byte) 0xC5, (byte) 0x01,
276                (byte) 0x1A, (byte) 0xE5, (byte) 0x4D, (byte) 0x2F, (byte) 0xCF, (byte) 0x5D,
277                (byte) 0xB2, (byte) 0xE7, (byte) 0xC7, (byte) 0xCB, (byte) 0x2C, (byte) 0xFF,
278                (byte) 0x51, (byte) 0x1B, (byte) 0x9D, (byte) 0xA4, (byte) 0x05, (byte) 0xEB,
279                (byte) 0x17, (byte) 0xD8, (byte) 0x97, (byte) 0x9D, (byte) 0x0C, (byte) 0x59,
280                (byte) 0x92, (byte) 0x8A, (byte) 0x03, (byte) 0x34, (byte) 0xFD, (byte) 0x16,
281                (byte) 0x0F, (byte) 0x2A, (byte) 0xF9, (byte) 0x7D, (byte) 0xC3, (byte) 0x41,
282                (byte) 0x0D, (byte) 0x06, (byte) 0x5A, (byte) 0x4B, (byte) 0x34, (byte) 0xD5,
283                (byte) 0xF5, (byte) 0x09, (byte) 0x1C, (byte) 0xCE, (byte) 0xA7, (byte) 0x19,
284                (byte) 0x6D, (byte) 0x04, (byte) 0x53, (byte) 0x71, (byte) 0xCC, (byte) 0x84,
285                (byte) 0xA0, (byte) 0xB2, (byte) 0xA0, (byte) 0x68, (byte) 0xA3, (byte) 0x40,
286                (byte) 0xC0, (byte) 0x67, (byte) 0x38, (byte) 0x96, (byte) 0x73, (byte) 0x2E,
287                (byte) 0x8E, (byte) 0x2A, (byte) 0x9D, (byte) 0x56, (byte) 0xE9, (byte) 0xAC,
288                (byte) 0xC7, (byte) 0xEC, (byte) 0x84, (byte) 0x7F, (byte) 0xFC, (byte) 0xE0,
289                (byte) 0x69, (byte) 0x03, (byte) 0x8B, (byte) 0x48, (byte) 0x64, (byte) 0x76,
290                (byte) 0x85, (byte) 0xA5, (byte) 0x10, (byte) 0xD9, (byte) 0x31, (byte) 0xC3,
291                (byte) 0x8B, (byte) 0x07, (byte) 0x48, (byte) 0x62, (byte) 0xF6, (byte) 0x68,
292                (byte) 0xF2, (byte) 0x96, (byte) 0xB2, (byte) 0x18, (byte) 0x5B, (byte) 0xFF,
293                (byte) 0x6D, (byte) 0xD1, (byte) 0x6B, (byte) 0xF5, (byte) 0xFD, (byte) 0x81,
294                (byte) 0xF1, (byte) 0xFD, (byte) 0x04, (byte) 0xF0, (byte) 0x9F, (byte) 0xB7,
295                (byte) 0x08, (byte) 0x95, (byte) 0x57, (byte) 0x48, (byte) 0x07, (byte) 0x00,
296                (byte) 0x52, (byte) 0xEC, (byte) 0x75, (byte) 0x91, (byte) 0x02, (byte) 0x11,
297                (byte) 0xA3, (byte) 0x64, (byte) 0x26, (byte) 0xCA,
298        });
299
300        AlgorithmParameterSpec spec = new DSAParameterSpec(p, q, g);
301        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
302                .setAlias(TEST_ALIAS_1)
303                .setKeyType("DSA")
304                .setKeySize(2048)
305                .setAlgorithmParameterSpec(spec)
306                .setSubject(TEST_DN_1)
307                .setSerialNumber(TEST_SERIAL_1)
308                .setStartDate(NOW)
309                .setEndDate(NOW_PLUS_10_YEARS)
310                .build());
311
312        final KeyPair pair = mGenerator.generateKeyPair();
313        assertNotNull("The KeyPair returned should not be null", pair);
314
315        assertKeyPairCorrect(pair, TEST_ALIAS_1, "DSA", 2048, spec, TEST_DN_1, TEST_SERIAL_1, NOW,
316                NOW_PLUS_10_YEARS);
317    }
318
319    public void testKeyPairGenerator_GenerateKeyPair_EC_Unencrypted_Success() throws Exception {
320        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
321                .setAlias(TEST_ALIAS_1)
322                .setKeyType("EC")
323                .setSubject(TEST_DN_1)
324                .setSerialNumber(TEST_SERIAL_1)
325                .setStartDate(NOW)
326                .setEndDate(NOW_PLUS_10_YEARS)
327                .build());
328
329        final KeyPair pair = mGenerator.generateKeyPair();
330        assertNotNull("The KeyPair returned should not be null", pair);
331
332        assertKeyPairCorrect(pair, TEST_ALIAS_1, "EC", 256, null, TEST_DN_1, TEST_SERIAL_1, NOW,
333                NOW_PLUS_10_YEARS);
334    }
335
336    public void testKeyPairGenerator_GenerateKeyPair_EC_P521_Unencrypted_Success() throws Exception {
337        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
338                .setAlias(TEST_ALIAS_1)
339                .setKeyType("EC")
340                .setKeySize(521)
341                .setSubject(TEST_DN_1)
342                .setSerialNumber(TEST_SERIAL_1)
343                .setStartDate(NOW)
344                .setEndDate(NOW_PLUS_10_YEARS)
345                .build());
346
347        final KeyPair pair = mGenerator.generateKeyPair();
348        assertNotNull("The KeyPair returned should not be null", pair);
349
350        assertKeyPairCorrect(pair, TEST_ALIAS_1, "EC", 521, null, TEST_DN_1, TEST_SERIAL_1, NOW,
351                NOW_PLUS_10_YEARS);
352    }
353
354    public void testKeyPairGenerator_GenerateKeyPair_RSA_Unencrypted_Success() throws Exception {
355        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
356                .setAlias(TEST_ALIAS_1)
357                .setSubject(TEST_DN_1)
358                .setSerialNumber(TEST_SERIAL_1)
359                .setStartDate(NOW)
360                .setEndDate(NOW_PLUS_10_YEARS)
361                .build());
362
363        final KeyPair pair = mGenerator.generateKeyPair();
364        assertNotNull("The KeyPair returned should not be null", pair);
365
366        assertKeyPairCorrect(pair, TEST_ALIAS_1, "RSA", 2048, null, TEST_DN_1, TEST_SERIAL_1, NOW,
367                NOW_PLUS_10_YEARS);
368    }
369
370    public void testKeyPairGenerator_GenerateKeyPair_RSA_WithParams_Unencrypted_Success()
371            throws Exception {
372        AlgorithmParameterSpec spec = new RSAKeyGenParameterSpec(1024, BigInteger.valueOf(3L));
373        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
374                .setAlias(TEST_ALIAS_1)
375                .setKeySize(1024)
376                .setAlgorithmParameterSpec(spec)
377                .setSubject(TEST_DN_1)
378                .setSerialNumber(TEST_SERIAL_1)
379                .setStartDate(NOW)
380                .setEndDate(NOW_PLUS_10_YEARS)
381                .build());
382
383        final KeyPair pair = mGenerator.generateKeyPair();
384        assertNotNull("The KeyPair returned should not be null", pair);
385
386        assertKeyPairCorrect(pair, TEST_ALIAS_1, "RSA", 1024, spec, TEST_DN_1, TEST_SERIAL_1, NOW,
387                NOW_PLUS_10_YEARS);
388    }
389
390    public void testKeyPairGenerator_GenerateKeyPair_Replaced_Success() throws Exception {
391        // Generate the first key
392        {
393            mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
394                    .setAlias(TEST_ALIAS_1)
395                    .setSubject(TEST_DN_1)
396                    .setSerialNumber(TEST_SERIAL_1)
397                    .setStartDate(NOW)
398                    .setEndDate(NOW_PLUS_10_YEARS)
399                    .build());
400            final KeyPair pair1 = mGenerator.generateKeyPair();
401            assertNotNull("The KeyPair returned should not be null", pair1);
402            assertKeyPairCorrect(pair1, TEST_ALIAS_1, "RSA", 2048, null, TEST_DN_1, TEST_SERIAL_1,
403                    NOW, NOW_PLUS_10_YEARS);
404        }
405
406        // Replace the original key
407        {
408            mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
409                    .setAlias(TEST_ALIAS_2)
410                    .setSubject(TEST_DN_2)
411                    .setSerialNumber(TEST_SERIAL_2)
412                    .setStartDate(NOW)
413                    .setEndDate(NOW_PLUS_10_YEARS)
414                    .build());
415            final KeyPair pair2 = mGenerator.generateKeyPair();
416            assertNotNull("The KeyPair returned should not be null", pair2);
417            assertKeyPairCorrect(pair2, TEST_ALIAS_2, "RSA", 2048, null, TEST_DN_2, TEST_SERIAL_2,
418                    NOW, NOW_PLUS_10_YEARS);
419        }
420    }
421
422    public void testKeyPairGenerator_GenerateKeyPair_Replaced_UnencryptedToEncrypted_Success()
423            throws Exception {
424        // Generate the first key
425        {
426            mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
427                    .setAlias(TEST_ALIAS_1)
428                    .setSubject(TEST_DN_1)
429                    .setSerialNumber(TEST_SERIAL_1)
430                    .setStartDate(NOW)
431                    .setEndDate(NOW_PLUS_10_YEARS)
432                    .build());
433            final KeyPair pair1 = mGenerator.generateKeyPair();
434            assertNotNull("The KeyPair returned should not be null", pair1);
435            assertKeyPairCorrect(pair1, TEST_ALIAS_1, "RSA", 2048, null, TEST_DN_1, TEST_SERIAL_1,
436                    NOW, NOW_PLUS_10_YEARS);
437        }
438
439        // Attempt to replace previous key
440        {
441            mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
442                    .setAlias(TEST_ALIAS_1)
443                    .setSubject(TEST_DN_2)
444                    .setSerialNumber(TEST_SERIAL_2)
445                    .setStartDate(NOW)
446                    .setEndDate(NOW_PLUS_10_YEARS)
447                    .setEncryptionRequired()
448                    .build());
449            try {
450                mGenerator.generateKeyPair();
451                fail("Should not be able to generate encrypted key while not initialized");
452            } catch (IllegalStateException expected) {
453            }
454
455            assertTrue(mAndroidKeyStore.password("1111"));
456            assertTrue(mAndroidKeyStore.isUnlocked());
457
458            final KeyPair pair2 = mGenerator.generateKeyPair();
459            assertNotNull("The KeyPair returned should not be null", pair2);
460            assertKeyPairCorrect(pair2, TEST_ALIAS_1, "RSA", 2048, null, TEST_DN_2, TEST_SERIAL_2,
461                    NOW, NOW_PLUS_10_YEARS);
462        }
463    }
464
465    private void assertKeyPairCorrect(KeyPair pair, String alias, String keyType, int keySize,
466            AlgorithmParameterSpec spec, X500Principal dn, BigInteger serial, Date start, Date end)
467            throws Exception {
468        final PublicKey pubKey = pair.getPublic();
469        assertNotNull("The PublicKey for the KeyPair should be not null", pubKey);
470        assertEquals(keyType, pubKey.getAlgorithm());
471
472        if ("DSA".equalsIgnoreCase(keyType)) {
473            DSAPublicKey dsaPubKey = (DSAPublicKey) pubKey;
474            DSAParams actualParams = dsaPubKey.getParams();
475            assertEquals(keySize, (actualParams.getP().bitLength() + 7) & ~7);
476            if (spec != null) {
477                DSAParameterSpec expectedParams = (DSAParameterSpec) spec;
478                assertEquals(expectedParams.getP(), actualParams.getP());
479                assertEquals(expectedParams.getQ(), actualParams.getQ());
480                assertEquals(expectedParams.getG(), actualParams.getG());
481            }
482        } else if ("EC".equalsIgnoreCase(keyType)) {
483            assertEquals("Curve should be what was specified during initialization", keySize,
484                    ((ECPublicKey) pubKey).getParams().getCurve().getField().getFieldSize());
485        } else if ("RSA".equalsIgnoreCase(keyType)) {
486            RSAPublicKey rsaPubKey = (RSAPublicKey) pubKey;
487            assertEquals("Modulus size should be what is specified during initialization",
488                    (keySize + 7) & ~7, (rsaPubKey.getModulus().bitLength() + 7) & ~7);
489            if (spec != null) {
490                RSAKeyGenParameterSpec params = (RSAKeyGenParameterSpec) spec;
491                assertEquals((keySize + 7) & ~7, (params.getKeysize() + 7) & ~7);
492                assertEquals(params.getPublicExponent(), rsaPubKey.getPublicExponent());
493            }
494        }
495
496        final PrivateKey privKey = pair.getPrivate();
497        assertNotNull("The PrivateKey for the KeyPair should be not null", privKey);
498        assertEquals(keyType, privKey.getAlgorithm());
499
500        final byte[] userCertBytes = mAndroidKeyStore.get(Credentials.USER_CERTIFICATE + alias);
501        assertNotNull("The user certificate should exist for the generated entry", userCertBytes);
502
503        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
504        final Certificate userCert = cf
505                .generateCertificate(new ByteArrayInputStream(userCertBytes));
506
507        assertTrue("Certificate should be in X.509 format", userCert instanceof X509Certificate);
508
509        final X509Certificate x509userCert = (X509Certificate) userCert;
510
511        assertEquals("PublicKey used to sign certificate should match one returned in KeyPair",
512                pubKey, x509userCert.getPublicKey());
513
514        assertEquals("The Subject DN should be the one passed into the params", dn,
515                x509userCert.getSubjectDN());
516
517        assertEquals("The Issuer DN should be the same as the Subject DN", dn,
518                x509userCert.getIssuerDN());
519
520        assertEquals("The Serial should be the one passed into the params", serial,
521                x509userCert.getSerialNumber());
522
523        assertDateEquals("The notBefore date should be the one passed into the params", start,
524                x509userCert.getNotBefore());
525
526        assertDateEquals("The notAfter date should be the one passed into the params", end,
527                x509userCert.getNotAfter());
528
529        x509userCert.verify(pubKey);
530
531        final byte[] caCerts = mAndroidKeyStore.get(Credentials.CA_CERTIFICATE + alias);
532        assertNull("A list of CA certificates should not exist for the generated entry", caCerts);
533
534        final byte[] pubKeyBytes = mAndroidKeyStore.getPubkey(Credentials.USER_PRIVATE_KEY + alias);
535        assertNotNull("The keystore should return the public key for the generated key",
536                pubKeyBytes);
537    }
538
539    private static void assertDateEquals(String message, Date date1, Date date2) throws Exception {
540        SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss");
541
542        String result1 = formatter.format(date1);
543        String result2 = formatter.format(date2);
544
545        assertEquals(message, result1, result2);
546    }
547}
548