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 17 package android.security; 18 19 import android.test.AndroidTestCase; 20 21 import java.io.ByteArrayInputStream; 22 import java.math.BigInteger; 23 import java.security.KeyPair; 24 import java.security.PrivateKey; 25 import java.security.PublicKey; 26 import java.security.SecureRandom; 27 import java.security.cert.Certificate; 28 import java.security.cert.CertificateFactory; 29 import java.security.cert.X509Certificate; 30 import java.util.Date; 31 32 import javax.security.auth.x500.X500Principal; 33 34 public class AndroidKeyPairGeneratorTest extends AndroidTestCase { 35 private android.security.KeyStore mAndroidKeyStore; 36 37 private java.security.KeyPairGenerator mGenerator; 38 39 private static final String TEST_ALIAS_1 = "test1"; 40 41 private static final String TEST_ALIAS_2 = "test2"; 42 43 private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1"); 44 45 private static final X500Principal TEST_DN_2 = new X500Principal("CN=test2"); 46 47 private static final BigInteger TEST_SERIAL_1 = BigInteger.ONE; 48 49 private static final BigInteger TEST_SERIAL_2 = BigInteger.valueOf(2L); 50 51 private static final long NOW_MILLIS = System.currentTimeMillis(); 52 53 /* We have to round this off because X509v3 doesn't store milliseconds. */ 54 private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L)); 55 56 @SuppressWarnings("deprecation") 57 private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1); 58 59 @Override setUp()60 protected void setUp() throws Exception { 61 mAndroidKeyStore = android.security.KeyStore.getInstance(); 62 63 assertTrue(mAndroidKeyStore.reset()); 64 65 assertEquals(android.security.KeyStore.State.UNINITIALIZED, mAndroidKeyStore.state()); 66 67 assertTrue(mAndroidKeyStore.password("1111")); 68 69 assertEquals(android.security.KeyStore.State.UNLOCKED, mAndroidKeyStore.state()); 70 71 assertEquals(0, mAndroidKeyStore.saw("").length); 72 73 mGenerator = java.security.KeyPairGenerator.getInstance(AndroidKeyPairGenerator.NAME); 74 } 75 testKeyPairGenerator_Initialize_Params_Success()76 public void testKeyPairGenerator_Initialize_Params_Success() throws Exception { 77 mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, 78 TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS)); 79 } 80 testKeyPairGenerator_Initialize_KeySize_Failure()81 public void testKeyPairGenerator_Initialize_KeySize_Failure() throws Exception { 82 try { 83 mGenerator.initialize(1024); 84 fail("KeyPairGenerator should not support setting the key size"); 85 } catch (IllegalArgumentException success) { 86 } 87 } 88 testKeyPairGenerator_Initialize_KeySizeAndSecureRandom_Failure()89 public void testKeyPairGenerator_Initialize_KeySizeAndSecureRandom_Failure() throws Exception { 90 try { 91 mGenerator.initialize(1024, new SecureRandom()); 92 fail("KeyPairGenerator should not support setting the key size"); 93 } catch (IllegalArgumentException success) { 94 } 95 } 96 testKeyPairGenerator_Initialize_ParamsAndSecureRandom_Failure()97 public void testKeyPairGenerator_Initialize_ParamsAndSecureRandom_Failure() throws Exception { 98 mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, 99 TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS), new SecureRandom()); 100 } 101 testKeyPairGenerator_GenerateKeyPair_Success()102 public void testKeyPairGenerator_GenerateKeyPair_Success() throws Exception { 103 mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, 104 TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS)); 105 106 final KeyPair pair = mGenerator.generateKeyPair(); 107 assertNotNull("The KeyPair returned should not be null", pair); 108 109 assertKeyPairCorrect(pair, TEST_ALIAS_1, TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS); 110 } 111 testKeyPairGenerator_GenerateKeyPair_Replaced_Success()112 public void testKeyPairGenerator_GenerateKeyPair_Replaced_Success() throws Exception { 113 // Generate the first key 114 { 115 mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, 116 TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS)); 117 final KeyPair pair1 = mGenerator.generateKeyPair(); 118 assertNotNull("The KeyPair returned should not be null", pair1); 119 assertKeyPairCorrect(pair1, TEST_ALIAS_1, TEST_DN_1, TEST_SERIAL_1, NOW, 120 NOW_PLUS_10_YEARS); 121 } 122 123 // Replace the original key 124 { 125 mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_2, 126 TEST_DN_2, TEST_SERIAL_2, NOW, NOW_PLUS_10_YEARS)); 127 final KeyPair pair2 = mGenerator.generateKeyPair(); 128 assertNotNull("The KeyPair returned should not be null", pair2); 129 assertKeyPairCorrect(pair2, TEST_ALIAS_2, TEST_DN_2, TEST_SERIAL_2, NOW, 130 NOW_PLUS_10_YEARS); 131 } 132 } 133 assertKeyPairCorrect(KeyPair pair, String alias, X500Principal dn, BigInteger serial, Date start, Date end)134 private void assertKeyPairCorrect(KeyPair pair, String alias, X500Principal dn, 135 BigInteger serial, Date start, Date end) throws Exception { 136 final PublicKey pubKey = pair.getPublic(); 137 assertNotNull("The PublicKey for the KeyPair should be not null", pubKey); 138 139 final PrivateKey privKey = pair.getPrivate(); 140 assertNotNull("The PrivateKey for the KeyPair should be not null", privKey); 141 142 final byte[] userCertBytes = mAndroidKeyStore.get(Credentials.USER_CERTIFICATE + alias); 143 assertNotNull("The user certificate should exist for the generated entry", userCertBytes); 144 145 final CertificateFactory cf = CertificateFactory.getInstance("X.509"); 146 final Certificate userCert = cf 147 .generateCertificate(new ByteArrayInputStream(userCertBytes)); 148 149 assertTrue("Certificate should be in X.509 format", userCert instanceof X509Certificate); 150 151 final X509Certificate x509userCert = (X509Certificate) userCert; 152 153 assertEquals("PublicKey used to sign certificate should match one returned in KeyPair", 154 pubKey, x509userCert.getPublicKey()); 155 156 assertEquals("The Subject DN should be the one passed into the params", dn, 157 x509userCert.getSubjectDN()); 158 159 assertEquals("The Issuer DN should be the same as the Subject DN", dn, 160 x509userCert.getIssuerDN()); 161 162 assertEquals("The Serial should be the one passed into the params", serial, 163 x509userCert.getSerialNumber()); 164 165 assertEquals("The notBefore date should be the one passed into the params", start, 166 x509userCert.getNotBefore()); 167 168 assertEquals("The notAfter date should be the one passed into the params", end, 169 x509userCert.getNotAfter()); 170 171 x509userCert.verify(pubKey); 172 173 final byte[] caCerts = mAndroidKeyStore.get(Credentials.CA_CERTIFICATE + alias); 174 assertNull("A list of CA certificates should not exist for the generated entry", caCerts); 175 176 final byte[] pubKeyBytes = mAndroidKeyStore.getPubkey(Credentials.USER_PRIVATE_KEY + alias); 177 assertNotNull("The keystore should return the public key for the generated key", 178 pubKeyBytes); 179 } 180 } 181