1 /* 2 * Copyright (C) 2009 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 package tests.targets.security; 17 18 import dalvik.annotation.TestLevel; 19 import dalvik.annotation.TestTargetNew; 20 import dalvik.annotation.TestTargets; 21 import java.io.ByteArrayInputStream; 22 import java.io.ByteArrayOutputStream; 23 import java.io.IOException; 24 import java.io.InputStream; 25 import java.security.KeyPair; 26 import java.security.KeyPairGenerator; 27 import java.security.KeyStore; 28 import java.security.KeyStore.Entry; 29 import java.security.KeyStore.PasswordProtection; 30 import java.security.KeyStore.PrivateKeyEntry; 31 import java.security.KeyStore.ProtectionParameter; 32 import java.security.KeyStoreException; 33 import java.security.NoSuchAlgorithmException; 34 import java.security.PrivateKey; 35 import java.security.UnrecoverableEntryException; 36 import java.security.cert.Certificate; 37 import java.security.cert.CertificateException; 38 import java.security.cert.CertificateFactory; 39 import junit.framework.TestCase; 40 41 public class KeyStoreTest extends TestCase { 42 43 private final String algorithmName; 44 private final byte[] keyStoreData; 45 private final String keyStorePassword; 46 47 public KeyStoreTest(String algorithmName, byte[] keyStoreData, 48 String keyStorePassword) { 49 this.algorithmName = algorithmName; 50 this.keyStoreData = keyStoreData; 51 this.keyStorePassword = keyStorePassword; 52 } 53 54 @TestTargets({ 55 @TestTargetNew( 56 level=TestLevel.ADDITIONAL, 57 method="getInstance", 58 args={String.class} 59 ), 60 @TestTargetNew( 61 level=TestLevel.ADDITIONAL, 62 method="load", 63 args={InputStream.class,char[].class} 64 ), 65 @TestTargetNew( 66 level=TestLevel.PARTIAL_COMPLETE, 67 method="method", 68 args={} 69 ) 70 }) 71 public void testKeyStoreLoad() { 72 KeyStore keyStore = null; 73 try { 74 keyStore = KeyStore.getInstance(algorithmName); 75 } catch (KeyStoreException e) { 76 fail(e.getMessage()); 77 } 78 79 try { 80 keyStore.load(new ByteArrayInputStream(keyStoreData), 81 keyStorePassword.toCharArray()); 82 } catch (NoSuchAlgorithmException e) { 83 fail(e.getMessage()); 84 } catch (CertificateException e) { 85 fail(e.getMessage()); 86 } catch (IOException e) { 87 fail(e.getMessage()); 88 } 89 90 try { 91 assertTrue("keystore is empty", keyStore.aliases() 92 .hasMoreElements()); 93 } catch (KeyStoreException e) { 94 fail(e.getMessage()); 95 } 96 } 97 98 @TestTargets({ 99 @TestTargetNew( 100 level=TestLevel.ADDITIONAL, 101 method="getInstance", 102 args={String.class} 103 ), 104 @TestTargetNew( 105 level=TestLevel.ADDITIONAL, 106 method="load", 107 args={InputStream.class,char[].class} 108 ), 109 @TestTargetNew( 110 level=TestLevel.ADDITIONAL, 111 method="setEntry", 112 args={String.class,Entry.class,ProtectionParameter.class} 113 ), 114 @TestTargetNew( 115 level=TestLevel.PARTIAL_COMPLETE, 116 method="method", 117 args={} 118 ) 119 }) 120 public void testKeyStoreCreate() { 121 KeyStore keyStore = null; 122 try { 123 keyStore = KeyStore.getInstance(algorithmName); 124 } catch (KeyStoreException e) { 125 fail(e.getMessage()); 126 } 127 128 try { 129 keyStore.load(null, "the secret password".toCharArray()); 130 } catch (NoSuchAlgorithmException e) { 131 fail(e.getMessage()); 132 } catch (CertificateException e) { 133 fail(e.getMessage()); 134 } catch (IOException e) { 135 fail(e.getMessage()); 136 } 137 138 CertificateFactory certificateFactory = null; 139 try { 140 certificateFactory = CertificateFactory.getInstance("X.509"); 141 } catch (CertificateException e) { 142 fail(e.getMessage()); 143 } 144 145 Certificate certificate = null; 146 try { 147 certificate = certificateFactory 148 .generateCertificate(new ByteArrayInputStream( 149 encodedCertificate.getBytes())); 150 } catch (CertificateException e) { 151 fail(e.getMessage()); 152 } 153 154 KeyPairGenerator generator = null; 155 try { 156 generator = KeyPairGenerator.getInstance(certificate.getPublicKey() 157 .getAlgorithm()); 158 } catch (NoSuchAlgorithmException e) { 159 fail(e.getMessage()); 160 } 161 162 KeyPair keyPair = generator.generateKeyPair(); 163 164 PrivateKeyEntry privateKeyEntry = new PrivateKeyEntry(keyPair 165 .getPrivate(), new Certificate[] {certificate}); 166 167 try { 168 keyStore.setEntry("aPrivateKey", privateKeyEntry, 169 new PasswordProtection("the key password".toCharArray())); 170 } catch (KeyStoreException e) { 171 fail(e.getMessage()); 172 } 173 174 try { 175 assertTrue(keyStore.containsAlias("aPrivateKey")); 176 } catch (KeyStoreException e) { 177 fail(e.getMessage()); 178 } 179 180 try { 181 PrivateKeyEntry entry = (PrivateKeyEntry) keyStore.getEntry( 182 "aPrivateKey", new PasswordProtection("the key password" 183 .toCharArray())); 184 PrivateKey privateKey = entry.getPrivateKey(); 185 assertEquals(keyPair.getPrivate(), privateKey); 186 } catch (NoSuchAlgorithmException e) { 187 fail(e.getMessage()); 188 } catch (UnrecoverableEntryException e) { 189 fail(e.getMessage()); 190 } catch (KeyStoreException e) { 191 fail(e.getMessage()); 192 } 193 194 try { 195 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 196 keyStore.store(stream, "the keystore password".toCharArray()); 197 assertTrue("keystore not written", stream.size() > 0); 198 } catch (KeyStoreException e) { 199 fail(e.getMessage()); 200 } catch (NoSuchAlgorithmException e) { 201 fail(e.getMessage()); 202 } catch (CertificateException e) { 203 fail(e.getMessage()); 204 } catch (IOException e) { 205 fail(e.getMessage()); 206 } 207 } 208 209 private String encodedCertificate = "-----BEGIN CERTIFICATE-----\n" 210 + "MIID0jCCAzugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBmjELMAkGA1UEBhMCVUsx\n" 211 + "EjAQBgNVBAgTCUhhbXBzaGlyZTETMBEGA1UEBxMKV2luY2hlc3RlcjETMBEGA1UE\n" 212 + "ChMKSUJNIFVLIEx0ZDEMMAoGA1UECxMDSlRDMRYwFAYDVQQDEw1QYXVsIEggQWJi\n" 213 + "b3R0MScwJQYJKoZIhvcNAQkBFhhQYXVsX0hfQWJib3R0QHVrLmlibS5jb20wHhcN\n" 214 + "MDQwNjIyMjA1MDU1WhcNMDUwNjIyMjA1MDU1WjCBmDELMAkGA1UEBhMCVUsxEjAQ\n" 215 + "BgNVBAgTCUhhbXBzaGlyZTETMBEGA1UEBxMKV2luY2hlc3RlcjETMBEGA1UEChMK\n" 216 + "SUJNIFVrIEx0ZDEMMAoGA1UECxMDSkVUMRQwEgYDVQQDEwtQYXVsIEFiYm90dDEn\n" 217 + "MCUGCSqGSIb3DQEJARYYUGF1bF9IX0FiYm90dEB1ay5pYm0uY29tMIGfMA0GCSqG\n" 218 + "SIb3DQEBAQUAA4GNADCBiQKBgQDitZBQ5d18ecNJpcnuKTraHYtqsAugoc95/L5Q\n" 219 + "28s3t1QAu2505qQR1MZaAkY7tDNyl1vPnZoym+Y06UswTrZoVYo/gPNeyWPMTsLA\n" 220 + "wzQvk5/6yhtE9ciH7B0SqYw6uSiDTbUY/zQ6qed+TsQhjlbn3PUHRjnI2P8A04cg\n" 221 + "LgYYGQIDAQABo4IBJjCCASIwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3Bl\n" 222 + "blNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFPplRPs65hUfxUBs\n" 223 + "6/Taq7nN8i1UMIHHBgNVHSMEgb8wgbyAFJOMtPAwlXdZLqE7DKU6xpL6FjFtoYGg\n" 224 + "pIGdMIGaMQswCQYDVQQGEwJVSzESMBAGA1UECBMJSGFtcHNoaXJlMRMwEQYDVQQH\n" 225 + "EwpXaW5jaGVzdGVyMRMwEQYDVQQKEwpJQk0gVUsgTHRkMQwwCgYDVQQLEwNKVEMx\n" 226 + "FjAUBgNVBAMTDVBhdWwgSCBBYmJvdHQxJzAlBgkqhkiG9w0BCQEWGFBhdWxfSF9B\n" 227 + "YmJvdHRAdWsuaWJtLmNvbYIBADANBgkqhkiG9w0BAQQFAAOBgQAnQ22Jw2HUrz7c\n" 228 + "VaOap31mTikuQ/CQxpwPYiSyTJ4s99eEzn+2yAk9tIDIJpqoay/fj+OLgPUQKIAo\n" 229 + "XpRVvmHlGE7UqMKebZtSZJQzs6VoeeKFhgHmqg8eVC2AsTc4ZswJmg4wCui5AH3a\n" 230 + "oqG7PIM3LxZqXYQlZiPSZ6kCpDOWVg==\n" 231 + "-----END CERTIFICATE-----\n"; 232 } 233