Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a00a2b33 authored by Brian Carlstrom's avatar Brian Carlstrom
Browse files

KeyChain API for credential installation

Bug: 3497064
Change-Id: I4ac4d8b5559496b1632d63c2129e2bafd240893f
parent afb60c36
Loading
Loading
Loading
Loading
+6 −10
Original line number Diff line number Diff line
@@ -21,31 +21,27 @@ import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import com.android.org.bouncycastle.jce.netscape.NetscapeCertRequest;
import com.android.org.bouncycastle.util.encoders.Base64;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.security.Credentials;
import android.security.KeyChain;
import android.util.Log;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.HashMap;

class CertTool {
final class CertTool {
    private static final String LOGTAG = "CertTool";

    private static final AlgorithmIdentifier MD5_WITH_RSA =
            new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption);

    static final String CERT = Credentials.CERTIFICATE;
    static final String PKCS12 = Credentials.PKCS12;

    private static HashMap<String, String> sCertificateTypeMap;
    static {
        sCertificateTypeMap = new HashMap<String, String>();
        sCertificateTypeMap.put("application/x-x509-ca-cert", CertTool.CERT);
        sCertificateTypeMap.put("application/x-x509-user-cert", CertTool.CERT);
        sCertificateTypeMap.put("application/x-pkcs12", CertTool.PKCS12);
        sCertificateTypeMap.put("application/x-x509-ca-cert", KeyChain.EXTRA_CERTIFICATE);
        sCertificateTypeMap.put("application/x-x509-user-cert", KeyChain.EXTRA_CERTIFICATE);
        sCertificateTypeMap.put("application/x-pkcs12", KeyChain.EXTRA_PKCS12);
    }

    static String[] getKeyStrengthList() {
+7 −20
Original line number Diff line number Diff line
@@ -60,16 +60,10 @@ public class Credentials {
    public static final String WIFI = "WIFI_";

    /** Data type for public keys. */
    public static final String PUBLIC_KEY = "KEY";
    public static final String EXTRA_PUBLIC_KEY = "KEY";

    /** Data type for private keys. */
    public static final String PRIVATE_KEY = "PKEY";

    /** Data type for certificates. */
    public static final String CERTIFICATE = "CERT";

    /** Data type for PKCS12. */
    public static final String PKCS12 = "PKCS12";
    public static final String EXTRA_PRIVATE_KEY = "PKEY";

    // historically used by Android
    public static final String EXTENSION_CRT = ".crt";
@@ -130,16 +124,9 @@ public class Credentials {
        }
    }

    private Intent createInstallIntent() {
        Intent intent = new Intent(INSTALL_ACTION);
        intent.setClassName("com.android.certinstaller",
                "com.android.certinstaller.CertInstallerMain");
        return intent;
    }

    public void install(Context context) {
        try {
            Intent intent = createInstallIntent();
            Intent intent = KeyChain.createInstallIntent();
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            Log.w(LOGTAG, e.toString());
@@ -148,9 +135,9 @@ public class Credentials {

    public void install(Context context, KeyPair pair) {
        try {
            Intent intent = createInstallIntent();
            intent.putExtra(PRIVATE_KEY, pair.getPrivate().getEncoded());
            intent.putExtra(PUBLIC_KEY, pair.getPublic().getEncoded());
            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());
@@ -159,7 +146,7 @@ public class Credentials {

    public void install(Context context, String type, byte[] value) {
        try {
            Intent intent = createInstallIntent();
            Intent intent = KeyChain.createInstallIntent();
            intent.putExtra(type, value);
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
+87 −1
Original line number Diff line number Diff line
@@ -89,30 +89,116 @@ public final class KeyChain {
    public static final String ACCOUNT_TYPE = "com.android.keychain";

    /**
     * Action to bring up the KeyChainActivity
     */
    private static final String ACTION_CHOOSER = "com.android.keychain.CHOOSER";

    /**
     * Extra for use with {@link #ACTION_CHOOSER}
     * @hide Also used by KeyChainActivity implementation
     */
    public static final String EXTRA_RESPONSE = "response";

    /**
     * Extra for use with {@link #ACTION_CHOOSER}
     * @hide Also used by KeyChainActivity implementation
     */
    public static final String EXTRA_HOST = "host";

    /**
     * Extra for use with {@link #ACTION_CHOOSER}
     * @hide Also used by KeyChainActivity implementation
     */
    public static final String EXTRA_PORT = "port";

    /**
     * Extra for use with {@link #ACTION_CHOOSER}
     * @hide Also used by KeyChainActivity implementation
     */
    public static final String EXTRA_ALIAS = "alias";

    /**
     * Extra for use with {@link #ACTION_CHOOSER}
     * @hide Also used by KeyChainActivity implementation
     */
    public static final String EXTRA_SENDER = "sender";

    /**
     * Action to bring up the CertInstaller
     */
    private static final String ACTION_INSTALL = "android.credentials.INSTALL";

    /**
     * Optional extra to specify a {@code String} credential name on
     * the {@code Intent} returned by {@link #createInstallIntent}.
     *
     * @hide TODO make public
     */
    // Compatible with old com.android.certinstaller.CredentialHelper.CERT_NAME_KEY
    public static final String EXTRA_NAME = "name";

    /**
     * Optional extra to specify an X.509 certificate to install on
     * the {@code Intent} returned by {@link #createInstallIntent}.
     * The extra value should be a PEM or ASN.1 DER encoded {@code
     * byte[]}. An {@link X509Certificate} can be converted to DER
     * encoded bytes with {@link X509Certificate#getEncoded}.
     *
     * <p>{@link #EXTRA_NAME} may be used to provide a default alias
     * name for the installed certificate.
     *
     * @hide TODO make public
     */
    // Compatible with old android.security.Credentials.CERTIFICATE
    public static final String EXTRA_CERTIFICATE = "CERT";

    /**
     * Optional extra for use with the {@code Intent} returned by
     * {@link #createInstallIntent} to specify a PKCS#12 key store to
     * install. The extra value should be a {@code byte[]}. The bytes
     * may come from an external source or be generated with {@link
     * KeyStore#store} on a "PKCS12" instance.
     *
     * <p>The user will be prompted for the password to load the key store.
     *
     * <p>The key store will be scanned for {@link
     * java.security.KeyStore.PrivateKeyEntry} entries and both the
     * private key and associated certificate chain will be installed.
     *
     * <p>{@link #EXTRA_NAME} may be used to provide a default alias
     * name for the installed credentials.
     *
     * @hide TODO make public
     */
    // Compatible with old android.security.Credentials.PKCS12
    public static final String EXTRA_PKCS12 = "PKCS12";

    /**
     * Returns an {@code Intent} that can be used for credential
     * installation. The intent may be used without any extras, in
     * which case the user will be able to install credentials from
     * their own source.
     *
     * <p>Alternatively, {@link #EXTRA_CERTIFICATE} or {@link
     * #EXTRA_PKCS12} maybe used to specify the bytes of an X.509
     * certificate or a PKCS#12 key store for installation. These
     * extras may be combined with {@link EXTRA_NAME} to provide a
     * default alias name for credentials being installed.
     *
     * <p>When used with {@link Activity#startActivityForResult},
     * {@link Activity#RESULT_OK} will be returned if a credential was
     * successfully installed, otherwise {@link
     * Activity#RESULT_CANCELED} will be returned.
     *
     * @hide TODO make public with createInstallIntent, EXTRA_NAME, EXTRA_CERTIFICATE, EXTRA_PKCS12
     */
    public static Intent createInstallIntent() {
        Intent intent = new Intent(ACTION_INSTALL);
        intent.setClassName("com.android.certinstaller",
                            "com.android.certinstaller.CertInstallerMain");
        return intent;
    }

    /**
     * Launches an {@code Activity} for the user to select the alias
     * for a private key and certificate pair for authentication. The
@@ -176,7 +262,7 @@ public final class KeyChain {
        if (response == null) {
            throw new NullPointerException("response == null");
        }
        Intent intent = new Intent("com.android.keychain.CHOOSER");
        Intent intent = new Intent(ACTION_CHOOSER);
        intent.putExtra(EXTRA_RESPONSE, new AliasResponse(activity, response));
        intent.putExtra(EXTRA_HOST, host);
        intent.putExtra(EXTRA_PORT, port);