summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xAndroid.mk1
-rwxr-xr-xAndroidManifest.xml1
-rw-r--r--res/layout/cert_chooser.xml60
-rw-r--r--res/layout/cert_item.xml58
-rwxr-xr-xres/values/strings.xml25
-rw-r--r--res/values/styles.xml26
-rw-r--r--src/com/android/keychain/KeyChainActivity.java284
-rw-r--r--tests/src/com/android/keychain/tests/KeyChainTestActivity.java39
8 files changed, 450 insertions, 44 deletions
diff --git a/Android.mk b/Android.mk
index ad6b85a..59557f2 100755
--- a/Android.mk
+++ b/Android.mk
@@ -18,6 +18,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_LIBRARIES := bouncycastle
LOCAL_PACKAGE_NAME := KeyChain
LOCAL_CERTIFICATE := platform
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 751b7da..efbcb8e 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -17,6 +17,7 @@
android:resource="@xml/authenticator"/>
</service>
<activity android:name="com.android.keychain.KeyChainActivity"
+ android:theme="@style/Transparent"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="com.android.keychain.CHOOSER"/>
diff --git a/res/layout/cert_chooser.xml b/res/layout/cert_chooser.xml
new file mode 100644
index 0000000..7381b4c
--- /dev/null
+++ b/res/layout/cert_chooser.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ >
+ <TextView
+ android:id="@+id/cert_chooser_context_message"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="6dip"
+ android:visibility="gone"
+ />
+ <ListView
+ android:id="@+id/cert_chooser_cert_list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:drawSelectorOnTop="false"
+ android:textFilterEnabled="true"
+ android:choiceMode="singleChoice"
+ android:visibility="gone"
+ />
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:background="@android:drawable/divider_horizontal_dark"
+ />
+ <TextView
+ android:id="@+id/cert_chooser_install_message"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="6dip"
+ />
+ <LinearLayout
+ android:gravity="right"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <Button
+ android:id="@+id/cert_chooser_install_button"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/install_new_cert_button_label"
+ android:layout_margin="6dip"
+ />
+ </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/cert_item.xml b/res/layout/cert_item.xml
new file mode 100644
index 0000000..b77e9fc
--- /dev/null
+++ b/res/layout/cert_item.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:paddingRight="?android:attr/scrollbarSize"
+ android:background="?android:attr/selectableItemBackground"
+ android:padding="15dip"
+ >
+ <RelativeLayout
+ android:layout_width="0px"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ >
+ <TextView
+ android:id="@+id/cert_item_alias"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ <TextView
+ android:id="@+id/cert_item_subject"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/cert_item_alias"
+ android:layout_alignLeft="@id/cert_item_alias"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+ </RelativeLayout>
+ <RadioButton
+ android:id="@+id/cert_item_selected"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:clickable="false"
+ android:focusable="false"
+ android:layout_weight="0"
+ />
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e208bed..9bd7cb0 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -16,4 +16,29 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Key Chain</string>
<string name="keychainUserLabel">keychain</string>
+
+ <!-- Dialog title when no certificates were found -->
+ <string name="title_no_certs">No certificates found</string>
+
+ <!-- Dialog title when at least one certificate was found -->
+ <string name="title_select_cert">Select certificate</string>
+
+ <!-- Used at top of dialog to identify requesting application -->
+ <string name="requesting_application">The application %s has requested a certificate. Selecting a certificate will grant the application the ability to use this identity with servers now and in the future.</string>
+
+ <!-- Used at top of dialog to identify requesting server (may be host:port or just host)-->
+ <string name="requesting_server">The application has identified the requesting server as %s but you should only grant the application access to the certificate if you trust the application.</string>
+
+ <!-- Label of button to send the user to the CertInstaller to install a certificate (arguments are constants for .pfx and .p12) -->
+ <string name="install_new_cert_message">You can install certificates from a PKCS#12 file with a %1$s or a %2$s extension located in external storage.</string>
+
+ <!-- Label of button to send the user to the CertInstaller to install a certificate -->
+ <string name="install_new_cert_button_label">Install</string>
+
+ <!-- Label of button to send the allow the application certificate request -->
+ <string name="allow_button">Allow</string>
+
+ <!-- Label of button to send the deny the application certificate request -->
+ <string name="deny_button">Deny</string>
+
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644
index 0000000..585b92e
--- /dev/null
+++ b/res/values/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2011 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.
+*/
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="Transparent">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsFloating">true</item>
+ </style>
+</resources>
diff --git a/src/com/android/keychain/KeyChainActivity.java b/src/com/android/keychain/KeyChainActivity.java
index 8b94344..1073556 100644
--- a/src/com/android/keychain/KeyChainActivity.java
+++ b/src/com/android/keychain/KeyChainActivity.java
@@ -16,21 +16,42 @@
package com.android.keychain;
-import android.app.ListActivity;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.PendingIntent;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.security.Credentials;
import android.security.IKeyChainAliasCallback;
import android.security.KeyChain;
import android.security.KeyStore;
+import android.view.LayoutInflater;
import android.view.View;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
import android.widget.ListView;
+import android.widget.RadioButton;
+import android.widget.TextView;
+import com.android.org.bouncycastle.asn1.x509.X509Name;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.security.auth.x500.X500Principal;
-public class KeyChainActivity extends ListActivity {
+public class KeyChainActivity extends Activity {
private static final String TAG = "KeyChainActivity";
@@ -38,21 +59,26 @@ public class KeyChainActivity extends ListActivity {
private static final int REQUEST_UNLOCK = 1;
+ private static final int DIALOG_CERT_CHOOSER = 0;
+
private static enum State { INITIAL, UNLOCK_REQUESTED };
private State mState;
+ // beware that some of these KeyStore operations such as saw and
+ // get do file I/O in the remote keystore process and while they
+ // do not cause StrictMode violations, they logically should not
+ // be done on the UI thread.
private KeyStore mKeyStore = KeyStore.getInstance();
+ private CertificateAdapter mCertificateAdapter;
+
+ // the KeyStore.state operation is safe to do on the UI thread, it
+ // does not do a file operation.
private boolean isKeyStoreUnlocked() {
return mKeyStore.state() == KeyStore.State.UNLOCKED;
}
- private boolean isKeyStoreEmpty() {
- String[] aliases = mKeyStore.saw(Credentials.USER_PRIVATE_KEY);
- return (aliases == null || aliases.length == 0);
- }
-
@Override public void onCreate(Bundle savedState) {
super.onCreate(savedState);
if (savedState == null) {
@@ -71,11 +97,6 @@ public class KeyChainActivity extends ListActivity {
// see if KeyStore has been unlocked, if not start activity to do so
switch (mState) {
case INITIAL:
- if (isKeyStoreEmpty()) {
- finish(null);
- return;
- }
-
if (!isKeyStoreUnlocked()) {
mState = State.UNLOCK_REQUESTED;
this.startActivityForResult(new Intent(Credentials.UNLOCK_ACTION),
@@ -86,7 +107,7 @@ public class KeyChainActivity extends ListActivity {
// onActivityResult is called with REQUEST_UNLOCK
return;
}
- showAliasList();
+ new AliasLoader().execute();
return;
case UNLOCK_REQUESTED:
// we've already asked, but have not heard back, probably just rotated.
@@ -97,38 +118,225 @@ public class KeyChainActivity extends ListActivity {
}
}
- private void showAliasList() {
+ private class AliasLoader extends AsyncTask<Void, Void, CertificateAdapter> {
+ @Override protected CertificateAdapter doInBackground(Void... params) {
+ String[] aliasArray = mKeyStore.saw(Credentials.USER_PRIVATE_KEY);
+ List<String> aliasList = ((aliasArray == null)
+ ? Collections.<String>emptyList()
+ : Arrays.asList(aliasArray));
+ Collections.sort(aliasList);
+ return new CertificateAdapter(aliasList);
+ }
+ @Override protected void onPostExecute(CertificateAdapter result) {
+ mCertificateAdapter = result;
+ showDialog(DIALOG_CERT_CHOOSER);
+ }
+ }
+
+ @Override protected Dialog onCreateDialog(int id, Bundle args) {
+ if (id == DIALOG_CERT_CHOOSER) {
+ return createCertChooserDialog();
+ }
+ throw new AssertionError();
+ }
- String[] aliases = mKeyStore.saw(Credentials.USER_PRIVATE_KEY);
- if (aliases == null || aliases.length == 0) {
+ private Dialog createCertChooserDialog() {
+ View view = View.inflate(this, R.layout.cert_chooser, null);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setView(view);
+ builder.setNegativeButton(R.string.deny_button, new DialogInterface.OnClickListener() {
+ @Override public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel(); // will cause OnDismissListener to be called
+ }
+ });
+
+ Resources res = getResources();
+
+ String title;
+ if (mCertificateAdapter.mAliases.isEmpty()) {
+ title = res.getString(R.string.title_no_certs);
+ } else {
+ title = res.getString(R.string.title_select_cert);
+ final ListView lv = (ListView) view.findViewById(R.id.cert_chooser_cert_list);
+ lv.setAdapter(mCertificateAdapter);
+ String alias = getIntent().getStringExtra(KeyChain.EXTRA_ALIAS);
+ if (alias != null) {
+ int position = mCertificateAdapter.mAliases.indexOf(alias);
+ if (position != -1) {
+ lv.setItemChecked(position, true);
+ }
+ }
+
+ builder.setPositiveButton(R.string.allow_button, new DialogInterface.OnClickListener() {
+ @Override public void onClick(DialogInterface dialog, int id) {
+ int pos = lv.getCheckedItemPosition();
+ String alias = ((pos != ListView.INVALID_POSITION)
+ ? mCertificateAdapter.getItem(pos)
+ : null);
+ finish(alias);
+ }
+ });
+
+ lv.setVisibility(View.VISIBLE);
+ }
+ builder.setTitle(title);
+
+ PendingIntent sender = getIntent().getParcelableExtra(KeyChain.EXTRA_SENDER);
+ if (sender == null) {
+ // if no sender, bail, we need to identify the app to the user securely.
finish(null);
- return;
- }
-
- final ArrayAdapter<String> adapter
- = new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1,
- aliases);
- setListAdapter(adapter);
-
- ListView lv = getListView();
- lv.setTextFilterEnabled(true);
- lv.setOnItemClickListener(new OnItemClickListener() {
- @Override public void onItemClick(AdapterView<?> parent,
- View view,
- int position,
- long id) {
- String alias = adapter.getItem(position);
- finish(alias);
+ }
+
+ // getTargetPackage guarantees that the returned string is
+ // supplied by the system, so that an application can not
+ // spoof its package.
+ String pkg = sender.getIntentSender().getTargetPackage();
+ PackageManager pm = getPackageManager();
+ CharSequence applicationLabel;
+ try {
+ applicationLabel = pm.getApplicationLabel(pm.getApplicationInfo(pkg, 0)).toString();
+ } catch (PackageManager.NameNotFoundException e) {
+ applicationLabel = pkg;
+ }
+ String appMessage = String.format(res.getString(R.string.requesting_application),
+ applicationLabel);
+
+ String contextMessage = appMessage;
+ String host = getIntent().getStringExtra(KeyChain.EXTRA_HOST);
+ if (host != null) {
+ String hostString = host;
+ int port = getIntent().getIntExtra(KeyChain.EXTRA_PORT, -1);
+ if (port != -1) {
+ hostString += ":" + port;
+ }
+ String hostMessage = String.format(res.getString(R.string.requesting_server),
+ hostString);
+ if (contextMessage == null) {
+ contextMessage = hostMessage;
+ } else {
+ contextMessage += " " + hostMessage;
+ }
+ }
+ TextView contextView = (TextView) view.findViewById(R.id.cert_chooser_context_message);
+ contextView.setText(contextMessage);
+ contextView.setVisibility(View.VISIBLE);
+
+ String installMessage = String.format(res.getString(R.string.install_new_cert_message),
+ Credentials.EXTENSION_PFX, Credentials.EXTENSION_P12);
+ TextView installTextView = (TextView) view.findViewById(R.id.cert_chooser_install_message);
+ installTextView.setText(installMessage);
+
+ Button installButton = (Button) view.findViewById(R.id.cert_chooser_install_button);
+ installButton.setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) {
+ // remove dialog so that we will recreate with
+ // possibly new content after install returns
+ removeDialog(DIALOG_CERT_CHOOSER);
+ Credentials.getInstance().install(KeyChainActivity.this);
+ }
+ });
+
+ Dialog dialog = builder.create();
+ dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override public void onCancel(DialogInterface dialog) {
+ finish(null);
}
});
+ return dialog;
+ }
+
+ private class CertificateAdapter extends BaseAdapter {
+ private final List<String> mAliases;
+ private final List<String> mSubjects = new ArrayList<String>();
+ private CertificateAdapter(List<String> aliases) {
+ mAliases = aliases;
+ mSubjects.addAll(Collections.nCopies(aliases.size(), (String) null));
+ }
+ @Override public int getCount() {
+ return mAliases.size();
+ }
+ @Override public String getItem(int position) {
+ return mAliases.get(position);
+ }
+ @Override public long getItemId(int position) {
+ return position;
+ }
+ @Override public View getView(final int position, View view, ViewGroup parent) {
+ ViewHolder holder;
+ if (view == null) {
+ LayoutInflater inflater = LayoutInflater.from(KeyChainActivity.this);
+ view = inflater.inflate(R.layout.cert_item, parent, false);
+ holder = new ViewHolder();
+ holder.mAliasTextView = (TextView) view.findViewById(R.id.cert_item_alias);
+ holder.mSubjectTextView = (TextView) view.findViewById(R.id.cert_item_subject);
+ holder.mRadioButton = (RadioButton) view.findViewById(R.id.cert_item_selected);
+ view.setTag(holder);
+ } else {
+ holder = (ViewHolder) view.getTag();
+ }
+
+ String alias = mAliases.get(position);
+
+ holder.mAliasTextView.setText(alias);
+
+ String subject = mSubjects.get(position);
+ if (subject == null) {
+ new CertLoader(position, holder.mSubjectTextView).execute();
+ } else {
+ holder.mSubjectTextView.setText(subject);
+ }
+
+ ListView lv = (ListView)parent;
+ holder.mRadioButton.setChecked(position == lv.getCheckedItemPosition());
+ return view;
+ }
+
+ private class CertLoader extends AsyncTask<Void, Void, String> {
+ private final int mPosition;
+ private final TextView mSubjectView;
+ private CertLoader(int position, TextView subjectView) {
+ mPosition = position;
+ mSubjectView = subjectView;
+ }
+ @Override protected String doInBackground(Void... params) {
+ String alias = mAliases.get(mPosition);
+ byte[] bytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+ if (bytes == null) {
+ return null;
+ }
+ InputStream in = new ByteArrayInputStream(bytes);
+ X509Certificate cert;
+ try {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ cert = (X509Certificate)cf.generateCertificate(in);
+ } catch (CertificateException ignored) {
+ return null;
+ }
+ // bouncycastle can handle the emailAddress OID of 1.2.840.113549.1.9.1
+ X500Principal subjectPrincipal = cert.getSubjectX500Principal();
+ X509Name subjectName = X509Name.getInstance(subjectPrincipal.getEncoded());
+ String subjectString = subjectName.toString(true, X509Name.DefaultSymbols);
+ return subjectString;
+ }
+ @Override protected void onPostExecute(String subjectString) {
+ mSubjects.set(mPosition, subjectString);
+ mSubjectView.setText(subjectString);
+ }
+ }
+ }
+
+ private static class ViewHolder {
+ TextView mAliasTextView;
+ TextView mSubjectTextView;
+ RadioButton mRadioButton;
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_UNLOCK:
if (isKeyStoreUnlocked()) {
- showAliasList();
+ showDialog(DIALOG_CERT_CHOOSER);
} else {
// user must have canceled unlock, give up
finish(null);
diff --git a/tests/src/com/android/keychain/tests/KeyChainTestActivity.java b/tests/src/com/android/keychain/tests/KeyChainTestActivity.java
index 6c280a6..c5ff34f 100644
--- a/tests/src/com/android/keychain/tests/KeyChainTestActivity.java
+++ b/tests/src/com/android/keychain/tests/KeyChainTestActivity.java
@@ -21,6 +21,7 @@ import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
+import android.os.StrictMode;
import android.security.Credentials;
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
@@ -59,7 +60,7 @@ public class KeyChainTestActivity extends Activity {
private TextView mTextView;
- private KeyChain mKeyChain;
+ private TestKeyStore mTestKeyStore;
private final Object mAliasLock = new Object();
private String mAlias;
@@ -79,6 +80,20 @@ public class KeyChainTestActivity extends Activity {
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+ .detectDiskReads()
+ .detectDiskWrites()
+ .detectAll()
+ .penaltyLog()
+ .penaltyDeath()
+ .build());
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+ .detectLeakedSqlLiteObjects()
+ .detectLeakedClosableObjects()
+ .penaltyLog()
+ .penaltyDeath()
+ .build());
+
mTextView = new TextView(this);
mTextView.setMovementMethod(new ScrollingMovementMethod());
setContentView(mTextView);
@@ -86,7 +101,7 @@ public class KeyChainTestActivity extends Activity {
log("Starting test...");
testKeyChainImproperUse();
- testCaInstall();
+ new SetupTestKeyStore().execute();
}
private void testKeyChainImproperUse() {
@@ -135,10 +150,20 @@ public class KeyChainTestActivity extends Activity {
}
}
+ private class SetupTestKeyStore extends AsyncTask<Void, Void, Void> {
+ @Override protected Void doInBackground(Void... params) {
+ mTestKeyStore = TestKeyStore.getServer();
+ return null;
+ }
+ @Override protected void onPostExecute(Void result) {
+ testCaInstall();
+ }
+ }
+
private void testCaInstall() {
try {
log("Requesting install of server's CA...");
- X509Certificate ca = TestKeyStore.getServer().getRootCertificate("RSA");
+ X509Certificate ca = mTestKeyStore.getRootCertificate("RSA");
Intent intent = new Intent("android.credentials.INSTALL");
intent.putExtra("name", TAG); // "name" = CredentialHelper.CERT_NAME_KEY
intent.putExtra(Credentials.CERTIFICATE, Credentials.convertToPem(ca));
@@ -164,8 +189,8 @@ public class KeyChainTestActivity extends Activity {
}
}
private URL startWebServer() throws Exception {
- KeyStore serverKeyStore = TestKeyStore.getServer().keyStore;
- char[] serverKeyStorePassword = TestKeyStore.getServer().storePassword;
+ KeyStore serverKeyStore = mTestKeyStore.keyStore;
+ char[] serverKeyStorePassword = mTestKeyStore.storePassword;
String kmfAlgoritm = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgoritm);
kmf.init(serverKeyStore, serverKeyStorePassword);
@@ -199,7 +224,9 @@ public class KeyChainTestActivity extends Activity {
log("KeyChainKeyManager chooseClientAlias...");
KeyChain.choosePrivateKeyAlias(KeyChainTestActivity.this, new AliasResponse(),
- null, null, null, -1);
+ keyTypes, issuers,
+ socket.getInetAddress().getHostName(), socket.getPort(),
+ "My Test Certificate");
String alias;
synchronized (mAliasLock) {
while (mAlias == null) {