This source file includes following definitions.
- JNINamespace
- getAlias
- getPrivateKey
- getCertificateChain
- doInBackground
- onPostExecute
- getAlias
- getPrivateKey
- getCertificateChain
- getAlias
- getPrivateKey
- getCertificateChain
- alias
- selectClientCertificate
- notifyClientCertificatesChangedOnIOThread
- nativeNotifyClientCertificatesChangedOnIOThread
- nativeOnSystemRequestCompletion
package org.chromium.chrome.browser;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
import android.security.KeyChainException;
import android.util.Log;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.ThreadUtils;
import org.chromium.net.AndroidPrivateKey;
import org.chromium.net.DefaultAndroidKeyStore;
import org.chromium.ui.base.WindowAndroid;
import java.security.Principal;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;
@JNINamespace("chrome::android")
public class SSLClientCertificateRequest {
static final String TAG = "SSLClientCertificateRequest";
private static final DefaultAndroidKeyStore sLocalKeyStore =
new DefaultAndroidKeyStore();
abstract static class CertAsyncTask extends AsyncTask<Void, Void, Void> {
private byte[][] mEncodedChain;
private AndroidPrivateKey mAndroidPrivateKey;
private final long mNativePtr;
CertAsyncTask(long nativePtr) {
mNativePtr = nativePtr;
}
abstract String getAlias();
abstract AndroidPrivateKey getPrivateKey(String alias);
abstract X509Certificate[] getCertificateChain(String alias);
@Override
protected Void doInBackground(Void... params) {
String alias = getAlias();
if (alias == null) return null;
AndroidPrivateKey key = getPrivateKey(alias);
X509Certificate[] chain = getCertificateChain(alias);
if (key == null || chain == null || chain.length == 0) {
Log.w(TAG, "Empty client certificate chain?");
return null;
}
byte[][] encodedChain = new byte[chain.length][];
try {
for (int i = 0; i < chain.length; ++i) {
encodedChain[i] = chain[i].getEncoded();
}
} catch (CertificateEncodingException e) {
Log.w(TAG, "Could not retrieve encoded certificate chain: " + e);
return null;
}
mEncodedChain = encodedChain;
mAndroidPrivateKey = key;
return null;
}
@Override
protected void onPostExecute(Void result) {
ThreadUtils.assertOnUiThread();
nativeOnSystemRequestCompletion(mNativePtr, mEncodedChain, mAndroidPrivateKey);
}
}
private static class CertAsyncTaskKeyChain extends CertAsyncTask {
final Context mContext;
final String mAlias;
CertAsyncTaskKeyChain(Context context, long nativePtr, String alias) {
super(nativePtr);
mContext = context;
assert alias != null;
mAlias = alias;
}
@Override
String getAlias() {
return mAlias;
}
@Override
AndroidPrivateKey getPrivateKey(String alias) {
try {
return sLocalKeyStore.createKey(KeyChain.getPrivateKey(mContext, alias));
} catch (KeyChainException e) {
Log.w(TAG, "KeyChainException when looking for '" + alias + "' certificate");
return null;
} catch (InterruptedException e) {
Log.w(TAG, "InterruptedException when looking for '" + alias + "'certificate");
return null;
}
}
@Override
X509Certificate[] getCertificateChain(String alias) {
try {
return KeyChain.getCertificateChain(mContext, alias);
} catch (KeyChainException e) {
Log.w(TAG, "KeyChainException when looking for '" + alias + "' certificate");
return null;
} catch (InterruptedException e) {
Log.w(TAG, "InterruptedException when looking for '" + alias + "'certificate");
return null;
}
}
}
private static class CertAsyncTaskPKCS11 extends CertAsyncTask {
private final PKCS11AuthenticationManager mPKCS11AuthManager;
private final String mHostName;
private final int mPort;
CertAsyncTaskPKCS11(long nativePtr, String hostName, int port,
PKCS11AuthenticationManager pkcs11CardAuthManager) {
super(nativePtr);
mHostName = hostName;
mPort = port;
mPKCS11AuthManager = pkcs11CardAuthManager;
}
@Override
String getAlias() {
return mPKCS11AuthManager.getClientCertificateAlias(mHostName, mPort);
}
@Override
AndroidPrivateKey getPrivateKey(String alias) {
return mPKCS11AuthManager.getPrivateKey(alias);
}
@Override
X509Certificate[] getCertificateChain(String alias) {
return mPKCS11AuthManager.getCertificateChain(alias);
}
}
private static class KeyChainCertSelectionCallback implements KeyChainAliasCallback {
private final long mNativePtr;
private final Context mContext;
KeyChainCertSelectionCallback(Context context, long nativePtr) {
mContext = context;
mNativePtr = nativePtr;
}
@Override
public void alias(final String alias) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
if (alias == null) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
nativeOnSystemRequestCompletion(mNativePtr, null, null);
}
});
} else {
new CertAsyncTaskKeyChain(mContext, mNativePtr, alias).execute();
}
}
});
}
}
@CalledByNative
private static boolean selectClientCertificate(final long nativePtr, final WindowAndroid window,
final String[] keyTypes, byte[][] encodedPrincipals, final String hostName,
final int port) {
ThreadUtils.assertOnUiThread();
final Activity activity = window.getActivity().get();
if (activity == null) {
Log.w(TAG, "Certificate request on GC'd activity.");
return false;
}
Principal[] principals = null;
if (encodedPrincipals.length > 0) {
principals = new X500Principal[encodedPrincipals.length];
try {
for (int n = 0; n < encodedPrincipals.length; n++) {
principals[n] = new X500Principal(encodedPrincipals[n]);
}
} catch (Exception e) {
Log.w(TAG, "Exception while decoding issuers list: " + e);
return false;
}
}
final Principal[] principalsForCallback = principals;
Runnable useSystemStore = new Runnable() {
@Override
public void run() {
KeyChainCertSelectionCallback callback =
new KeyChainCertSelectionCallback(activity.getApplicationContext(),
nativePtr);
KeyChain.choosePrivateKeyAlias(activity, callback, keyTypes, principalsForCallback,
hostName, port, null);
}
};
final Context appContext = activity.getApplicationContext();
final PKCS11AuthenticationManager smartCardAuthManager =
((ChromiumApplication) appContext).getPKCS11AuthenticationManager();
if (smartCardAuthManager.isPKCS11AuthEnabled()) {
Runnable useSmartCard = new Runnable() {
@Override
public void run() {
new CertAsyncTaskPKCS11(nativePtr, hostName, port,
smartCardAuthManager).execute();
}
};
Runnable cancelRunnable = new Runnable() {
@Override
public void run() {
nativeOnSystemRequestCompletion(nativePtr, null, null);
}
};
KeyStoreSelectionDialog selectionDialog = new KeyStoreSelectionDialog(
useSystemStore, useSmartCard, cancelRunnable);
selectionDialog.show(activity.getFragmentManager(), null);
} else {
useSystemStore.run();
}
return true;
}
public static void notifyClientCertificatesChangedOnIOThread() {
Log.d(TAG, "ClientCertificatesChanged!");
nativeNotifyClientCertificatesChangedOnIOThread();
}
private static native void nativeNotifyClientCertificatesChangedOnIOThread();
private static native void nativeOnSystemRequestCompletion(
long requestPtr, byte[][] certChain, AndroidPrivateKey androidKey);
}