239 lines
8.3 KiB
Java
Raw Normal View History

/*
* Copyright (C) 2009 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.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.android.org.bouncycastle.util.io.pem.PemObject;
import com.android.org.bouncycastle.util.io.pem.PemReader;
import com.android.org.bouncycastle.util.io.pem.PemWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
/**
* {@hide}
*/
public class Credentials {
private static final String LOGTAG = "Credentials";
2009-09-21 11:53:59 +08:00
public static final String INSTALL_ACTION = "android.credentials.INSTALL";
public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER";
public static final String UNLOCK_ACTION = "com.android.credentials.UNLOCK";
/** Key prefix for CA certificates. */
public static final String CA_CERTIFICATE = "CACERT_";
/** Key prefix for user certificates. */
public static final String USER_CERTIFICATE = "USRCERT_";
/** Key prefix for user private keys. */
public static final String USER_PRIVATE_KEY = "USRPKEY_";
/** Key prefix for VPN. */
public static final String VPN = "VPN_";
/** Key prefix for WIFI. */
public static final String WIFI = "WIFI_";
/** Key containing suffix of lockdown VPN profile. */
public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN";
/** Data type for public keys. */
public static final String EXTRA_PUBLIC_KEY = "KEY";
/** Data type for private keys. */
public static final String EXTRA_PRIVATE_KEY = "PKEY";
Replace KeyChainActivity placeholder UI with more polished dialog (1 of 5) frameworks/base Extended KeyChain.chooserPrivateKeyAlias to allow caller to supply preferred choice to be selected in chooser. This allows Email settings to highlight the current choice when allowing user to change settings. keystore/java/android/security/KeyChain.java api/current.txt Implemented KeyChain functionality to pass host and port information to KeyChainActivity for display. keystore/java/android/security/KeyChain.java KeyChain now sends a PendingIntent as part of the Intent it sends to the KeyChainActivity which can be used to identify the caller in reliable way. keystore/java/android/security/KeyChain.java Moved .pfx/.p12/.cer/.crt constants to Credentials for reuse. Added Credentials.install variant with no value for use from KeyChainActivity keystore/java/android/security/Credentials.java packages/apps/CertInstaller Source of extension constants now in Credentials src/com/android/certinstaller/CertFile.java packages/apps/Browser Have browser supply host and port information to KeyChain.choosePrivateKeyAlias Tracking KeyChain.choosePrivateKeyAlias API change src/com/android/browser/Tab.java packages/apps/Email Tracking KeyChain.choosePrivateKeyAlias API change src/com/android/email/view/CertificateSelector.java packages/apps/KeyChain KeyChain now depends on bouncycastle X509Name for formatting X500Principals, since the 4 X500Principal formatting options could not format emailAddress attributes in a human readable way and its the most important attribute to display for client certificates in most cases. Android.mk Changing the UI to a dialog, make the activity style transparent. AndroidManifest.xml res/values/styles.xml Layout for chooser dialog res/layout/cert_chooser.xml Layout for list items in chooser res/layout/cert_item.xml New resources for dialog including comments for translators. res/values/strings.xml New dialog based KeyChainActivity. Now also shows requesting app and requesting server. Now can preselect a specified alias. New link directly to CertInstaller. src/com/android/keychain/KeyChainActivity.java Fix KeyChainTestActivity to work with TestKeyStore changes that were causing network activity on the UI to look up the name of localhost. Also track KeyChain.choosePrivateKeyAlias API change. tests/src/com/android/keychain/tests/KeyChainTestActivity.java Change-Id: I07128fba8750f9a6bcb9c6be5da04df992403d69
2011-06-24 02:13:23 -07:00
// historically used by Android
public static final String EXTENSION_CRT = ".crt";
public static final String EXTENSION_P12 = ".p12";
// commonly used on Windows
public static final String EXTENSION_CER = ".cer";
public static final String EXTENSION_PFX = ".pfx";
/**
* Intent extra: install the certificate bundle as this UID instead of
* system.
*/
public static final String EXTRA_INSTALL_AS_UID = "install_as_uid";
/**
* Intent extra: name for the user's private key.
*/
public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name";
/**
* Intent extra: data for the user's private key in PEM-encoded PKCS#8.
*/
public static final String EXTRA_USER_PRIVATE_KEY_DATA = "user_private_key_data";
/**
* Intent extra: name for the user's certificate.
*/
public static final String EXTRA_USER_CERTIFICATE_NAME = "user_certificate_name";
/**
* Intent extra: data for the user's certificate in PEM-encoded X.509.
*/
public static final String EXTRA_USER_CERTIFICATE_DATA = "user_certificate_data";
/**
* Intent extra: name for CA certificate chain
*/
public static final String EXTRA_CA_CERTIFICATES_NAME = "ca_certificates_name";
/**
* Intent extra: data for CA certificate chain in PEM-encoded X.509.
*/
public static final String EXTRA_CA_CERTIFICATES_DATA = "ca_certificates_data";
/**
* Convert objects to a PEM format which is used for
* CA_CERTIFICATE and USER_CERTIFICATE entries.
*/
public static byte[] convertToPem(Certificate... objects)
throws IOException, CertificateEncodingException {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(bao, StandardCharsets.US_ASCII);
PemWriter pw = new PemWriter(writer);
for (Certificate o : objects) {
pw.writeObject(new PemObject("CERTIFICATE", o.getEncoded()));
}
pw.close();
return bao.toByteArray();
}
/**
* Convert objects from PEM format, which is used for
* CA_CERTIFICATE and USER_CERTIFICATE entries.
*/
public static List<X509Certificate> convertFromPem(byte[] bytes)
throws IOException, CertificateException {
ByteArrayInputStream bai = new ByteArrayInputStream(bytes);
Reader reader = new InputStreamReader(bai, StandardCharsets.US_ASCII);
PemReader pr = new PemReader(reader);
CertificateFactory cf = CertificateFactory.getInstance("X509");
List<X509Certificate> result = new ArrayList<X509Certificate>();
PemObject o;
while ((o = pr.readPemObject()) != null) {
if (o.getType().equals("CERTIFICATE")) {
Certificate c = cf.generateCertificate(new ByteArrayInputStream(o.getContent()));
result.add((X509Certificate) c);
} else {
throw new IllegalArgumentException("Unknown type " + o.getType());
}
}
pr.close();
return result;
}
2009-09-21 11:53:59 +08:00
private static Credentials singleton;
public static Credentials getInstance() {
if (singleton == null) {
singleton = new Credentials();
}
return singleton;
}
public void unlock(Context context) {
try {
Intent intent = new Intent(UNLOCK_ACTION);
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.w(LOGTAG, e.toString());
}
}
Replace KeyChainActivity placeholder UI with more polished dialog (1 of 5) frameworks/base Extended KeyChain.chooserPrivateKeyAlias to allow caller to supply preferred choice to be selected in chooser. This allows Email settings to highlight the current choice when allowing user to change settings. keystore/java/android/security/KeyChain.java api/current.txt Implemented KeyChain functionality to pass host and port information to KeyChainActivity for display. keystore/java/android/security/KeyChain.java KeyChain now sends a PendingIntent as part of the Intent it sends to the KeyChainActivity which can be used to identify the caller in reliable way. keystore/java/android/security/KeyChain.java Moved .pfx/.p12/.cer/.crt constants to Credentials for reuse. Added Credentials.install variant with no value for use from KeyChainActivity keystore/java/android/security/Credentials.java packages/apps/CertInstaller Source of extension constants now in Credentials src/com/android/certinstaller/CertFile.java packages/apps/Browser Have browser supply host and port information to KeyChain.choosePrivateKeyAlias Tracking KeyChain.choosePrivateKeyAlias API change src/com/android/browser/Tab.java packages/apps/Email Tracking KeyChain.choosePrivateKeyAlias API change src/com/android/email/view/CertificateSelector.java packages/apps/KeyChain KeyChain now depends on bouncycastle X509Name for formatting X500Principals, since the 4 X500Principal formatting options could not format emailAddress attributes in a human readable way and its the most important attribute to display for client certificates in most cases. Android.mk Changing the UI to a dialog, make the activity style transparent. AndroidManifest.xml res/values/styles.xml Layout for chooser dialog res/layout/cert_chooser.xml Layout for list items in chooser res/layout/cert_item.xml New resources for dialog including comments for translators. res/values/strings.xml New dialog based KeyChainActivity. Now also shows requesting app and requesting server. Now can preselect a specified alias. New link directly to CertInstaller. src/com/android/keychain/KeyChainActivity.java Fix KeyChainTestActivity to work with TestKeyStore changes that were causing network activity on the UI to look up the name of localhost. Also track KeyChain.choosePrivateKeyAlias API change. tests/src/com/android/keychain/tests/KeyChainTestActivity.java Change-Id: I07128fba8750f9a6bcb9c6be5da04df992403d69
2011-06-24 02:13:23 -07:00
public void install(Context context) {
try {
Intent intent = KeyChain.createInstallIntent();
Replace KeyChainActivity placeholder UI with more polished dialog (1 of 5) frameworks/base Extended KeyChain.chooserPrivateKeyAlias to allow caller to supply preferred choice to be selected in chooser. This allows Email settings to highlight the current choice when allowing user to change settings. keystore/java/android/security/KeyChain.java api/current.txt Implemented KeyChain functionality to pass host and port information to KeyChainActivity for display. keystore/java/android/security/KeyChain.java KeyChain now sends a PendingIntent as part of the Intent it sends to the KeyChainActivity which can be used to identify the caller in reliable way. keystore/java/android/security/KeyChain.java Moved .pfx/.p12/.cer/.crt constants to Credentials for reuse. Added Credentials.install variant with no value for use from KeyChainActivity keystore/java/android/security/Credentials.java packages/apps/CertInstaller Source of extension constants now in Credentials src/com/android/certinstaller/CertFile.java packages/apps/Browser Have browser supply host and port information to KeyChain.choosePrivateKeyAlias Tracking KeyChain.choosePrivateKeyAlias API change src/com/android/browser/Tab.java packages/apps/Email Tracking KeyChain.choosePrivateKeyAlias API change src/com/android/email/view/CertificateSelector.java packages/apps/KeyChain KeyChain now depends on bouncycastle X509Name for formatting X500Principals, since the 4 X500Principal formatting options could not format emailAddress attributes in a human readable way and its the most important attribute to display for client certificates in most cases. Android.mk Changing the UI to a dialog, make the activity style transparent. AndroidManifest.xml res/values/styles.xml Layout for chooser dialog res/layout/cert_chooser.xml Layout for list items in chooser res/layout/cert_item.xml New resources for dialog including comments for translators. res/values/strings.xml New dialog based KeyChainActivity. Now also shows requesting app and requesting server. Now can preselect a specified alias. New link directly to CertInstaller. src/com/android/keychain/KeyChainActivity.java Fix KeyChainTestActivity to work with TestKeyStore changes that were causing network activity on the UI to look up the name of localhost. Also track KeyChain.choosePrivateKeyAlias API change. tests/src/com/android/keychain/tests/KeyChainTestActivity.java Change-Id: I07128fba8750f9a6bcb9c6be5da04df992403d69
2011-06-24 02:13:23 -07:00
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.w(LOGTAG, e.toString());
}
}
public void install(Context context, KeyPair pair) {
try {
Intent intent = KeyChain.createInstallIntent();
intent.putExtra(EXTRA_PRIVATE_KEY, pair.getPrivate().getEncoded());
intent.putExtra(EXTRA_PUBLIC_KEY, pair.getPublic().getEncoded());
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.w(LOGTAG, e.toString());
}
}
public void install(Context context, String type, byte[] value) {
try {
Intent intent = KeyChain.createInstallIntent();
intent.putExtra(type, value);
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.w(LOGTAG, e.toString());
}
}
/**
* Delete all types (private key, certificate, CA certificate) for a
* particular {@code alias}. All three can exist for any given alias.
* Returns {@code true} if there was at least one of those types.
*/
static boolean deleteAllTypesForAlias(KeyStore keystore, String alias) {
/*
* Make sure every type is deleted. There can be all three types, so
* don't use a conditional here.
*/
return keystore.delKey(Credentials.USER_PRIVATE_KEY + alias)
| deleteCertificateTypesForAlias(keystore, alias);
}
/**
* Delete all types (private key, certificate, CA certificate) for a
* particular {@code alias}. All three can exist for any given alias.
* Returns {@code true} if there was at least one of those types.
*/
static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias) {
/*
* Make sure every certificate type is deleted. There can be two types,
* so don't use a conditional here.
*/
return keystore.delete(Credentials.USER_CERTIFICATE + alias)
| keystore.delete(Credentials.CA_CERTIFICATE + alias);
}
}