summaryrefslogtreecommitdiffstats
path: root/keystore/tests
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2012-08-20 10:48:46 -0700
committerKenny Root <kroot@google.com>2012-08-22 08:52:55 -0700
commitdb026710ec0adcf7f72dfb24c65d38a882ee26d8 (patch)
treecff080fbecd17c5d6e6a60a7bc2adccbd6761b20 /keystore/tests
parente29df16cb57b69995df597e8a6d95d986c1c43fc (diff)
downloadframeworks_base-db026710ec0adcf7f72dfb24c65d38a882ee26d8.zip
frameworks_base-db026710ec0adcf7f72dfb24c65d38a882ee26d8.tar.gz
frameworks_base-db026710ec0adcf7f72dfb24c65d38a882ee26d8.tar.bz2
Add KeyPairGenerator for Android keystore
This allows end-users to generate keys in the keystore without the private part of the key ever needing to leave the device. The generation process also generates a self-signed certificate. Change-Id: I114ffb8e0cbe3b1edaae7e69e8aa578cb835efc9
Diffstat (limited to 'keystore/tests')
-rw-r--r--keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java118
-rw-r--r--keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java180
2 files changed, 298 insertions, 0 deletions
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
new file mode 100644
index 0000000..e6a3750
--- /dev/null
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.test.AndroidTestCase;
+
+import java.math.BigInteger;
+import java.util.Date;
+
+import javax.security.auth.x500.X500Principal;
+
+public class AndroidKeyPairGeneratorSpecTest extends AndroidTestCase {
+ private static final String TEST_ALIAS_1 = "test1";
+
+ private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
+
+ private static final long NOW_MILLIS = System.currentTimeMillis();
+
+ private static final BigInteger SERIAL_1 = BigInteger.ONE;
+
+ /* We have to round this off because X509v3 doesn't store milliseconds. */
+ private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L));
+
+ @SuppressWarnings("deprecation")
+ private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1);
+
+ public void testConstructor_Success() throws Exception {
+ AndroidKeyPairGeneratorSpec spec = new AndroidKeyPairGeneratorSpec(getContext(),
+ TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW, NOW_PLUS_10_YEARS);
+
+ assertEquals("Context should be the one specified", getContext(), spec.getContext());
+
+ assertEquals("Alias should be the one specified", TEST_ALIAS_1, spec.getKeystoreAlias());
+
+ assertEquals("subjectDN should be the one specified", TEST_DN_1, spec.getSubjectDN());
+
+ assertEquals("startDate should be the one specified", NOW, spec.getStartDate());
+
+ assertEquals("endDate should be the one specified", NOW_PLUS_10_YEARS, spec.getEndDate());
+ }
+
+ public void testConstructor_NullContext_Failure() throws Exception {
+ try {
+ new AndroidKeyPairGeneratorSpec(null, TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
+ NOW_PLUS_10_YEARS);
+ fail("Should throw IllegalArgumentException when context is null");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testConstructor_NullKeystoreAlias_Failure() throws Exception {
+ try {
+ new AndroidKeyPairGeneratorSpec(getContext(), null, TEST_DN_1, SERIAL_1, NOW,
+ NOW_PLUS_10_YEARS);
+ fail("Should throw IllegalArgumentException when keystoreAlias is null");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testConstructor_NullSubjectDN_Failure() throws Exception {
+ try {
+ new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, null, SERIAL_1, NOW,
+ NOW_PLUS_10_YEARS);
+ fail("Should throw IllegalArgumentException when subjectDN is null");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testConstructor_NullSerial_Failure() throws Exception {
+ try {
+ new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, null, NOW,
+ NOW_PLUS_10_YEARS);
+ fail("Should throw IllegalArgumentException when startDate is null");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testConstructor_NullStartDate_Failure() throws Exception {
+ try {
+ new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1, null,
+ NOW_PLUS_10_YEARS);
+ fail("Should throw IllegalArgumentException when startDate is null");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testConstructor_NullEndDate_Failure() throws Exception {
+ try {
+ new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
+ null);
+ fail("Should throw IllegalArgumentException when keystoreAlias is null");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testConstructor_EndBeforeStart_Failure() throws Exception {
+ try {
+ new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1,
+ NOW_PLUS_10_YEARS, NOW);
+ fail("Should throw IllegalArgumentException when end is before start");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+}
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
new file mode 100644
index 0000000..d108caa
--- /dev/null
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.test.AndroidTestCase;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import javax.security.auth.x500.X500Principal;
+
+public class AndroidKeyPairGeneratorTest extends AndroidTestCase {
+ private android.security.KeyStore mAndroidKeyStore;
+
+ private java.security.KeyPairGenerator mGenerator;
+
+ private static final String TEST_ALIAS_1 = "test1";
+
+ private static final String TEST_ALIAS_2 = "test2";
+
+ private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
+
+ private static final X500Principal TEST_DN_2 = new X500Principal("CN=test2");
+
+ private static final BigInteger TEST_SERIAL_1 = BigInteger.ONE;
+
+ private static final BigInteger TEST_SERIAL_2 = BigInteger.valueOf(2L);
+
+ private static final long NOW_MILLIS = System.currentTimeMillis();
+
+ /* We have to round this off because X509v3 doesn't store milliseconds. */
+ private static final Date NOW = new Date(NOW_MILLIS - (NOW_MILLIS % 1000L));
+
+ @SuppressWarnings("deprecation")
+ private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1);
+
+ @Override
+ protected void setUp() throws Exception {
+ mAndroidKeyStore = android.security.KeyStore.getInstance();
+
+ assertTrue(mAndroidKeyStore.reset());
+
+ assertEquals(android.security.KeyStore.State.UNINITIALIZED, mAndroidKeyStore.state());
+
+ assertTrue(mAndroidKeyStore.password("1111"));
+
+ assertEquals(android.security.KeyStore.State.UNLOCKED, mAndroidKeyStore.state());
+
+ assertEquals(0, mAndroidKeyStore.saw("").length);
+
+ mGenerator = java.security.KeyPairGenerator.getInstance(AndroidKeyPairGenerator.NAME);
+ }
+
+ public void testKeyPairGenerator_Initialize_Params_Success() throws Exception {
+ mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
+ TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
+ }
+
+ public void testKeyPairGenerator_Initialize_KeySize_Failure() throws Exception {
+ try {
+ mGenerator.initialize(1024);
+ fail("KeyPairGenerator should not support setting the key size");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testKeyPairGenerator_Initialize_KeySizeAndSecureRandom_Failure() throws Exception {
+ try {
+ mGenerator.initialize(1024, new SecureRandom());
+ fail("KeyPairGenerator should not support setting the key size");
+ } catch (IllegalArgumentException success) {
+ }
+ }
+
+ public void testKeyPairGenerator_Initialize_ParamsAndSecureRandom_Failure() throws Exception {
+ mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
+ TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS), new SecureRandom());
+ }
+
+ public void testKeyPairGenerator_GenerateKeyPair_Success() throws Exception {
+ mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
+ TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
+
+ final KeyPair pair = mGenerator.generateKeyPair();
+ assertNotNull("The KeyPair returned should not be null", pair);
+
+ assertKeyPairCorrect(pair, TEST_ALIAS_1, TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS);
+ }
+
+ public void testKeyPairGenerator_GenerateKeyPair_Replaced_Success() throws Exception {
+ // Generate the first key
+ {
+ mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1,
+ TEST_DN_1, TEST_SERIAL_1, NOW, NOW_PLUS_10_YEARS));
+ final KeyPair pair1 = mGenerator.generateKeyPair();
+ assertNotNull("The KeyPair returned should not be null", pair1);
+ assertKeyPairCorrect(pair1, TEST_ALIAS_1, TEST_DN_1, TEST_SERIAL_1, NOW,
+ NOW_PLUS_10_YEARS);
+ }
+
+ // Replace the original key
+ {
+ mGenerator.initialize(new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_2,
+ TEST_DN_2, TEST_SERIAL_2, NOW, NOW_PLUS_10_YEARS));
+ final KeyPair pair2 = mGenerator.generateKeyPair();
+ assertNotNull("The KeyPair returned should not be null", pair2);
+ assertKeyPairCorrect(pair2, TEST_ALIAS_2, TEST_DN_2, TEST_SERIAL_2, NOW,
+ NOW_PLUS_10_YEARS);
+ }
+ }
+
+ private void assertKeyPairCorrect(KeyPair pair, String alias, X500Principal dn,
+ BigInteger serial, Date start, Date end) throws Exception {
+ final PublicKey pubKey = pair.getPublic();
+ assertNotNull("The PublicKey for the KeyPair should be not null", pubKey);
+
+ final PrivateKey privKey = pair.getPrivate();
+ assertNotNull("The PrivateKey for the KeyPair should be not null", privKey);
+
+ final byte[] userCertBytes = mAndroidKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+ assertNotNull("The user certificate should exist for the generated entry", userCertBytes);
+
+ final CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ final Certificate userCert = cf
+ .generateCertificate(new ByteArrayInputStream(userCertBytes));
+
+ assertTrue("Certificate should be in X.509 format", userCert instanceof X509Certificate);
+
+ final X509Certificate x509userCert = (X509Certificate) userCert;
+
+ assertEquals("PublicKey used to sign certificate should match one returned in KeyPair",
+ pubKey, x509userCert.getPublicKey());
+
+ assertEquals("The Subject DN should be the one passed into the params", dn,
+ x509userCert.getSubjectDN());
+
+ assertEquals("The Issuer DN should be the same as the Subject DN", dn,
+ x509userCert.getIssuerDN());
+
+ assertEquals("The Serial should be the one passed into the params", serial,
+ x509userCert.getSerialNumber());
+
+ assertEquals("The notBefore date should be the one passed into the params", start,
+ x509userCert.getNotBefore());
+
+ assertEquals("The notAfter date should be the one passed into the params", end,
+ x509userCert.getNotAfter());
+
+ x509userCert.verify(pubKey);
+
+ final byte[] caCerts = mAndroidKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+ assertNull("A list of CA certificates should not exist for the generated entry", caCerts);
+
+ final byte[] pubKeyBytes = mAndroidKeyStore.getPubkey(Credentials.USER_PRIVATE_KEY + alias);
+ assertNotNull("The keystore should return the public key for the generated key",
+ pubKeyBytes);
+ }
+}