Loading keystore/java/android/security/CertTool.java +180 −40 Original line number Diff line number Diff line Loading @@ -16,6 +16,12 @@ package android.security; import android.content.Context; import android.content.Intent; import android.security.Keystore; import android.text.TextUtils; import android.util.Log; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.cert.Certificate; Loading @@ -23,16 +29,11 @@ import java.security.cert.CertificateException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import android.content.Context; import android.content.Intent; import android.security.Keystore; import android.text.TextUtils; import android.util.Log; import java.util.ArrayList; /** * The CertTool class provides the functions to list the certs/keys, * generate the certificate request(csr) and store the certificate into * generate the certificate request(csr) and store certificates into * keystore. * * {@hide} Loading @@ -51,19 +52,129 @@ public class CertTool { /** Keystore namespace for user private keys. */ public static final String USER_KEY = "USRKEY"; /** Action string for adding certificates to keystore. */ public static final String ACTION_ADD_CREDENTIAL = "android.security.ADD_CREDENTIAL"; public static final String KEY_TYPE_NAME = "typeName"; public static final String KEY_ITEM = "item"; public static final String KEY_NAMESPACE = "namespace"; public static final String KEY_DESCRIPTION = "description"; /** Action string for installing certificates to keystore from sdcard. */ public static final String ACTION_INSTALL_CERT_FROM_SDCARD = "android.security.INSTALL_CERT_FROM_SDCARD"; /** Dialog title for adding a CA certificate. */ public static final String TITLE_CA_CERT = "CA Certificate"; /** Dialog title for adding a user certificate. */ public static final String TITLE_USER_CERT = "User Certificate"; public static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore"; /** Dialog title for adding a user private key. */ public static final String TITLE_PRIVATE_KEY = "Private Key"; /** Dialog title for adding a PKCS12 keystore. */ public static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore"; public static final int INCORRECT_PKCS12_PASSPHRASE = -100; /** * The builder class for building an add-credential-to-keystore intent. */ public static class AddCredentialIntentBuilder { private Intent mIntent; private int mCount; /** * Creates a builder to build a add-credential-to-keystore intent. * * @param title title of the dialog for adding this credential * @param descriptions description strings to show on the dialog */ public AddCredentialIntentBuilder(String title, String... descriptions) { Intent intent = new Intent(ACTION_ADD_CREDENTIAL); intent.putExtra(KEY_TITLE, title); int i = 0; for (String description : descriptions) { intent.putExtra(KEY_DESCRIPTION + (i++), description); } mIntent = intent; } /** * Adds credential data to the intent. * * @param namespace the namespace of the keystore to add the credential * data to * @param data the credential data * @return this builder */ public AddCredentialIntentBuilder addCredential(String namespace, byte[] data) { mIntent.putExtra(KEY_NAMESPACE + mCount, namespace); mIntent.putExtra(KEY_ITEM + mCount, data); mCount++; return this; } /** Returns the intent. */ public Intent build() { return mIntent; } } /** * Request for adding credential data to keystore. */ public static class AddCredentialRequest { private Intent mIntent; /** * Creates an add-credential-data-to-keystore request. * * @param intent an add-credential-data-to-keystore intent * @see AddCredentialIntentBuilder */ public AddCredentialRequest(Intent intent) { mIntent = intent; } /** Returns the dialog title. */ public String getTitle() { return mIntent.getStringExtra(KEY_TITLE); } /** * Returns the i'th credential data. * @return the data or null if not exists */ public byte[] getDataAt(int i) { return mIntent.getByteArrayExtra(KEY_ITEM + i); } /** * Returns the namespace of the i'th credential data. * @return the namespace string or null if missing */ public String getNamespaceAt(int i) { return mIntent.getStringExtra(KEY_NAMESPACE + i); } /** Returns the descriptions of the credential data. */ public String[] getDescriptions() { ArrayList<String> list = new ArrayList<String>(); for (int i = 0; ; i++) { String s = mIntent.getStringExtra(KEY_DESCRIPTION + i); if (s == null) break; list.add(s); } return list.toArray(new String[list.size()]); } } private static final String KEY_TITLE = "typeName"; private static final String KEY_ITEM = "item"; private static final String KEY_NAMESPACE = "namespace"; private static final String KEY_DESCRIPTION = "description"; private static final String TAG = "CertTool"; private static final String UNKNOWN = "Unknown"; private static final String ISSUER_NAME = "Issuer Name:"; Loading @@ -86,33 +197,55 @@ public class CertTool { private native String getPrivateKeyPEM(int handle); private native void freeX509Certificate(int handle); private static CertTool singleton = null; private static CertTool sSingleton = null; private CertTool() { } public static final CertTool getInstance() { if (singleton == null) { singleton = new CertTool(); if (sSingleton == null) { sSingleton = new CertTool(); } return singleton; return sSingleton; } /** * Gets the full key to retrieve the user private key from the keystore. * @see #getAllUserCertificateKeys() */ public String getUserPrivateKey(String key) { return USER_KEY + KEYNAME_DELIMITER + key; } /** * Gets the full key to retrieve the user certificate from the keystore. * @see #getAllUserCertificateKeys() */ public String getUserCertificate(String key) { return USER_CERTIFICATE + KEYNAME_DELIMITER + key; } /** * Gets the full key to retrieve the CA certificate from the keystore. * @see #getAllCaCertificateKeys() */ public String getCaCertificate(String key) { return CA_CERTIFICATE + KEYNAME_DELIMITER + key; } /** * Gets all the keys to the user certificates/private keys stored in the * keystore. * @see #getUserCertificate(String) * @see #getUserPrivateKey(String) */ public String[] getAllUserCertificateKeys() { return sKeystore.listKeys(USER_KEY); } /** * Gets all the keys to the CA certificates stored in the keystore. * @see #getCaCertificate(String) */ public String[] getAllCaCertificateKeys() { return sKeystore.listKeys(CA_CERTIFICATE); } Loading @@ -126,29 +259,21 @@ public class CertTool { return 1024; } /** * Generates a key pair. * * @param keyStrengthIndex index to the array of supported key strengths; * see {@link #getSupportedKeyStrenghs()} * @param challenge the challenge string for generating the pair * @param dirName (not used) * @return a certificate request from the resulted public key */ public String generateKeyPair(int keyStrengthIndex, String challenge, String dirName) { return generateCertificateRequest(getKeyLength(keyStrengthIndex), challenge); } private Intent prepareIntent(String title, byte[] data, String namespace, String issuer, String distinctName) { Intent intent = new Intent(ACTION_ADD_CREDENTIAL); intent.putExtra(KEY_TYPE_NAME, title); intent.putExtra(KEY_ITEM + "0", data); intent.putExtra(KEY_NAMESPACE + "0", namespace); intent.putExtra(KEY_DESCRIPTION + "0", ISSUER_NAME + issuer); intent.putExtra(KEY_DESCRIPTION + "1", DISTINCT_NAME + distinctName); return intent; } private void addExtraIntentInfo(Intent intent, String namespace, String data) { intent.putExtra(KEY_ITEM + "1", data.getBytes()); intent.putExtra(KEY_NAMESPACE + "1", namespace); } private int extractAndStoreKeysFromPkcs12(int handle, String keyname) { int ret, i = 0; String pemData; Loading @@ -171,6 +296,7 @@ public class CertTool { return 0; } /** Adds a PKCS12 keystore to the keystore. */ public int addPkcs12Keystore(byte[] p12Data, String password, String keyname) { int handle, ret; Loading @@ -184,27 +310,35 @@ public class CertTool { return ret; } /** * Adds a certificate to the keystore. * * @param data the certificate data * @param context the context to send an add-credential-to-keystore intent */ public synchronized void addCertificate(byte[] data, Context context) { int handle; Intent intent = null; Log.i("CertTool", "addCertificate()"); if (isPkcs12Keystore(data)) { intent = prepareIntent(TITLE_PKCS12_KEYSTORE, data, USER_KEY, UNKNOWN, UNKNOWN); intent = prepareIntent(TITLE_PKCS12_KEYSTORE, UNKNOWN, UNKNOWN) .addCredential(USER_KEY, data).build(); } else if ((handle = generateX509Certificate(data)) != 0) { String issuer = getIssuerDN(handle); String distinctName = getCertificateDN(handle); String privateKeyPEM = getPrivateKeyPEM(handle); if (isCaCertificate(handle)) { intent = prepareIntent(TITLE_CA_CERT, data, CA_CERTIFICATE, issuer, distinctName); intent = prepareIntent(TITLE_CA_CERT, issuer, distinctName) .addCredential(CA_CERTIFICATE, data).build(); } else { intent = prepareIntent(TITLE_USER_CERT, data, USER_CERTIFICATE, issuer, distinctName); AddCredentialIntentBuilder builder = prepareIntent(TITLE_USER_CERT, issuer, distinctName) .addCredential(USER_CERTIFICATE, data); if (!TextUtils.isEmpty(privateKeyPEM)) { addExtraIntentInfo(intent, USER_KEY, privateKeyPEM); builder.addCredential(USER_KEY, privateKeyPEM.getBytes()); } intent = builder.build(); } freeX509Certificate(handle); } Loading @@ -214,4 +348,10 @@ public class CertTool { Log.w("CertTool", "incorrect data for addCertificate()"); } } private AddCredentialIntentBuilder prepareIntent( String title, String issuer, String distinctName) { return new AddCredentialIntentBuilder(title, ISSUER_NAME + issuer, DISTINCT_NAME + distinctName); } } keystore/java/android/security/Keystore.java +6 −4 Original line number Diff line number Diff line Loading @@ -22,8 +22,9 @@ package android.security; */ public abstract class Keystore { private static final String TAG = "Keystore"; private static final String[] NOTFOUND = new String[0]; /** Action to unlock (or initialize) the keystore. */ public static final String ACTION_UNLOCK_CREDENTIAL_STORAGE = "android.security.UNLOCK_CREDENTIAL_STORAGE"; // Keystore States public static final int BOOTUP = 0; Loading @@ -31,8 +32,9 @@ public abstract class Keystore { public static final int LOCKED = 2; public static final int UNLOCKED = 3; /** */ private static final String TAG = "Keystore"; private static final String[] NOTFOUND = new String[0]; public static Keystore getInstance() { return new FileKeystore(); } Loading Loading
keystore/java/android/security/CertTool.java +180 −40 Original line number Diff line number Diff line Loading @@ -16,6 +16,12 @@ package android.security; import android.content.Context; import android.content.Intent; import android.security.Keystore; import android.text.TextUtils; import android.util.Log; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.cert.Certificate; Loading @@ -23,16 +29,11 @@ import java.security.cert.CertificateException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import android.content.Context; import android.content.Intent; import android.security.Keystore; import android.text.TextUtils; import android.util.Log; import java.util.ArrayList; /** * The CertTool class provides the functions to list the certs/keys, * generate the certificate request(csr) and store the certificate into * generate the certificate request(csr) and store certificates into * keystore. * * {@hide} Loading @@ -51,19 +52,129 @@ public class CertTool { /** Keystore namespace for user private keys. */ public static final String USER_KEY = "USRKEY"; /** Action string for adding certificates to keystore. */ public static final String ACTION_ADD_CREDENTIAL = "android.security.ADD_CREDENTIAL"; public static final String KEY_TYPE_NAME = "typeName"; public static final String KEY_ITEM = "item"; public static final String KEY_NAMESPACE = "namespace"; public static final String KEY_DESCRIPTION = "description"; /** Action string for installing certificates to keystore from sdcard. */ public static final String ACTION_INSTALL_CERT_FROM_SDCARD = "android.security.INSTALL_CERT_FROM_SDCARD"; /** Dialog title for adding a CA certificate. */ public static final String TITLE_CA_CERT = "CA Certificate"; /** Dialog title for adding a user certificate. */ public static final String TITLE_USER_CERT = "User Certificate"; public static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore"; /** Dialog title for adding a user private key. */ public static final String TITLE_PRIVATE_KEY = "Private Key"; /** Dialog title for adding a PKCS12 keystore. */ public static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore"; public static final int INCORRECT_PKCS12_PASSPHRASE = -100; /** * The builder class for building an add-credential-to-keystore intent. */ public static class AddCredentialIntentBuilder { private Intent mIntent; private int mCount; /** * Creates a builder to build a add-credential-to-keystore intent. * * @param title title of the dialog for adding this credential * @param descriptions description strings to show on the dialog */ public AddCredentialIntentBuilder(String title, String... descriptions) { Intent intent = new Intent(ACTION_ADD_CREDENTIAL); intent.putExtra(KEY_TITLE, title); int i = 0; for (String description : descriptions) { intent.putExtra(KEY_DESCRIPTION + (i++), description); } mIntent = intent; } /** * Adds credential data to the intent. * * @param namespace the namespace of the keystore to add the credential * data to * @param data the credential data * @return this builder */ public AddCredentialIntentBuilder addCredential(String namespace, byte[] data) { mIntent.putExtra(KEY_NAMESPACE + mCount, namespace); mIntent.putExtra(KEY_ITEM + mCount, data); mCount++; return this; } /** Returns the intent. */ public Intent build() { return mIntent; } } /** * Request for adding credential data to keystore. */ public static class AddCredentialRequest { private Intent mIntent; /** * Creates an add-credential-data-to-keystore request. * * @param intent an add-credential-data-to-keystore intent * @see AddCredentialIntentBuilder */ public AddCredentialRequest(Intent intent) { mIntent = intent; } /** Returns the dialog title. */ public String getTitle() { return mIntent.getStringExtra(KEY_TITLE); } /** * Returns the i'th credential data. * @return the data or null if not exists */ public byte[] getDataAt(int i) { return mIntent.getByteArrayExtra(KEY_ITEM + i); } /** * Returns the namespace of the i'th credential data. * @return the namespace string or null if missing */ public String getNamespaceAt(int i) { return mIntent.getStringExtra(KEY_NAMESPACE + i); } /** Returns the descriptions of the credential data. */ public String[] getDescriptions() { ArrayList<String> list = new ArrayList<String>(); for (int i = 0; ; i++) { String s = mIntent.getStringExtra(KEY_DESCRIPTION + i); if (s == null) break; list.add(s); } return list.toArray(new String[list.size()]); } } private static final String KEY_TITLE = "typeName"; private static final String KEY_ITEM = "item"; private static final String KEY_NAMESPACE = "namespace"; private static final String KEY_DESCRIPTION = "description"; private static final String TAG = "CertTool"; private static final String UNKNOWN = "Unknown"; private static final String ISSUER_NAME = "Issuer Name:"; Loading @@ -86,33 +197,55 @@ public class CertTool { private native String getPrivateKeyPEM(int handle); private native void freeX509Certificate(int handle); private static CertTool singleton = null; private static CertTool sSingleton = null; private CertTool() { } public static final CertTool getInstance() { if (singleton == null) { singleton = new CertTool(); if (sSingleton == null) { sSingleton = new CertTool(); } return singleton; return sSingleton; } /** * Gets the full key to retrieve the user private key from the keystore. * @see #getAllUserCertificateKeys() */ public String getUserPrivateKey(String key) { return USER_KEY + KEYNAME_DELIMITER + key; } /** * Gets the full key to retrieve the user certificate from the keystore. * @see #getAllUserCertificateKeys() */ public String getUserCertificate(String key) { return USER_CERTIFICATE + KEYNAME_DELIMITER + key; } /** * Gets the full key to retrieve the CA certificate from the keystore. * @see #getAllCaCertificateKeys() */ public String getCaCertificate(String key) { return CA_CERTIFICATE + KEYNAME_DELIMITER + key; } /** * Gets all the keys to the user certificates/private keys stored in the * keystore. * @see #getUserCertificate(String) * @see #getUserPrivateKey(String) */ public String[] getAllUserCertificateKeys() { return sKeystore.listKeys(USER_KEY); } /** * Gets all the keys to the CA certificates stored in the keystore. * @see #getCaCertificate(String) */ public String[] getAllCaCertificateKeys() { return sKeystore.listKeys(CA_CERTIFICATE); } Loading @@ -126,29 +259,21 @@ public class CertTool { return 1024; } /** * Generates a key pair. * * @param keyStrengthIndex index to the array of supported key strengths; * see {@link #getSupportedKeyStrenghs()} * @param challenge the challenge string for generating the pair * @param dirName (not used) * @return a certificate request from the resulted public key */ public String generateKeyPair(int keyStrengthIndex, String challenge, String dirName) { return generateCertificateRequest(getKeyLength(keyStrengthIndex), challenge); } private Intent prepareIntent(String title, byte[] data, String namespace, String issuer, String distinctName) { Intent intent = new Intent(ACTION_ADD_CREDENTIAL); intent.putExtra(KEY_TYPE_NAME, title); intent.putExtra(KEY_ITEM + "0", data); intent.putExtra(KEY_NAMESPACE + "0", namespace); intent.putExtra(KEY_DESCRIPTION + "0", ISSUER_NAME + issuer); intent.putExtra(KEY_DESCRIPTION + "1", DISTINCT_NAME + distinctName); return intent; } private void addExtraIntentInfo(Intent intent, String namespace, String data) { intent.putExtra(KEY_ITEM + "1", data.getBytes()); intent.putExtra(KEY_NAMESPACE + "1", namespace); } private int extractAndStoreKeysFromPkcs12(int handle, String keyname) { int ret, i = 0; String pemData; Loading @@ -171,6 +296,7 @@ public class CertTool { return 0; } /** Adds a PKCS12 keystore to the keystore. */ public int addPkcs12Keystore(byte[] p12Data, String password, String keyname) { int handle, ret; Loading @@ -184,27 +310,35 @@ public class CertTool { return ret; } /** * Adds a certificate to the keystore. * * @param data the certificate data * @param context the context to send an add-credential-to-keystore intent */ public synchronized void addCertificate(byte[] data, Context context) { int handle; Intent intent = null; Log.i("CertTool", "addCertificate()"); if (isPkcs12Keystore(data)) { intent = prepareIntent(TITLE_PKCS12_KEYSTORE, data, USER_KEY, UNKNOWN, UNKNOWN); intent = prepareIntent(TITLE_PKCS12_KEYSTORE, UNKNOWN, UNKNOWN) .addCredential(USER_KEY, data).build(); } else if ((handle = generateX509Certificate(data)) != 0) { String issuer = getIssuerDN(handle); String distinctName = getCertificateDN(handle); String privateKeyPEM = getPrivateKeyPEM(handle); if (isCaCertificate(handle)) { intent = prepareIntent(TITLE_CA_CERT, data, CA_CERTIFICATE, issuer, distinctName); intent = prepareIntent(TITLE_CA_CERT, issuer, distinctName) .addCredential(CA_CERTIFICATE, data).build(); } else { intent = prepareIntent(TITLE_USER_CERT, data, USER_CERTIFICATE, issuer, distinctName); AddCredentialIntentBuilder builder = prepareIntent(TITLE_USER_CERT, issuer, distinctName) .addCredential(USER_CERTIFICATE, data); if (!TextUtils.isEmpty(privateKeyPEM)) { addExtraIntentInfo(intent, USER_KEY, privateKeyPEM); builder.addCredential(USER_KEY, privateKeyPEM.getBytes()); } intent = builder.build(); } freeX509Certificate(handle); } Loading @@ -214,4 +348,10 @@ public class CertTool { Log.w("CertTool", "incorrect data for addCertificate()"); } } private AddCredentialIntentBuilder prepareIntent( String title, String issuer, String distinctName) { return new AddCredentialIntentBuilder(title, ISSUER_NAME + issuer, DISTINCT_NAME + distinctName); } }
keystore/java/android/security/Keystore.java +6 −4 Original line number Diff line number Diff line Loading @@ -22,8 +22,9 @@ package android.security; */ public abstract class Keystore { private static final String TAG = "Keystore"; private static final String[] NOTFOUND = new String[0]; /** Action to unlock (or initialize) the keystore. */ public static final String ACTION_UNLOCK_CREDENTIAL_STORAGE = "android.security.UNLOCK_CREDENTIAL_STORAGE"; // Keystore States public static final int BOOTUP = 0; Loading @@ -31,8 +32,9 @@ public abstract class Keystore { public static final int LOCKED = 2; public static final int UNLOCKED = 3; /** */ private static final String TAG = "Keystore"; private static final String[] NOTFOUND = new String[0]; public static Keystore getInstance() { return new FileKeystore(); } Loading