| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser; | 5 package org.chromium.chrome.browser; |
| 6 | 6 |
| 7 import android.app.Activity; | 7 import android.app.Activity; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.os.AsyncTask; | 9 import android.os.AsyncTask; |
| 10 import android.security.KeyChain; | 10 import android.security.KeyChain; |
| 11 import android.security.KeyChainAliasCallback; | 11 import android.security.KeyChainAliasCallback; |
| 12 import android.security.KeyChainException; | 12 import android.security.KeyChainException; |
| 13 import android.util.Log; | 13 import android.util.Log; |
| 14 | 14 |
| 15 import org.chromium.base.ActivityStatus; | 15 import org.chromium.base.ActivityStatus; |
| 16 import org.chromium.base.CalledByNative; | 16 import org.chromium.base.CalledByNative; |
| 17 import org.chromium.base.JNINamespace; | 17 import org.chromium.base.JNINamespace; |
| 18 import org.chromium.base.ThreadUtils; | 18 import org.chromium.base.ThreadUtils; |
| 19 import org.chromium.net.AndroidKeyStoreLocalImpl; |
| 20 import org.chromium.net.AndroidKeyStoreRemote; |
| 21 import org.chromium.net.AndroidPrivateKey; |
| 19 | 22 |
| 20 import java.security.Principal; | 23 import java.security.Principal; |
| 21 import java.security.PrivateKey; | |
| 22 import java.security.cert.CertificateEncodingException; | 24 import java.security.cert.CertificateEncodingException; |
| 23 import java.security.cert.X509Certificate; | 25 import java.security.cert.X509Certificate; |
| 24 | 26 |
| 25 import javax.security.auth.x500.X500Principal; | 27 import javax.security.auth.x500.X500Principal; |
| 26 | 28 |
| 27 /** | 29 /** |
| 28 * Handles selection of client certificate on the Java side. This class is respo
nsible for selection | 30 * Handles selection of client certificate on the Java side. This class is respo
nsible for selection |
| 29 * of the client certificate to be used for authentication and retrieval of the
private key and full | 31 * of the client certificate to be used for authentication and retrieval of the
private key and full |
| 30 * certificate chain. | 32 * certificate chain. |
| 31 * | 33 * |
| 32 * The entry point is selectClientCertificate() and it will be called on the UI
thread. Then the | 34 * The entry point is selectClientCertificate() and it will be called on the UI
thread. Then the |
| 33 * class will construct and run an appropriate CertAsyncTask, that will run in b
ackground, and | 35 * class will construct and run an appropriate CertAsyncTask, that will run in b
ackground, and |
| 34 * finally pass the results back to the UI thread, which will return to the nati
ve code. | 36 * finally pass the results back to the UI thread, which will return to the nati
ve code. |
| 35 */ | 37 */ |
| 36 @JNINamespace("chrome::android") | 38 @JNINamespace("chrome::android") |
| 37 class SSLClientCertificateRequest { | 39 public class SSLClientCertificateRequest { |
| 38 static final String TAG = "SSLClientCertificateRequest"; | 40 static final String TAG = "SSLClientCertificateRequest"; |
| 39 | 41 |
| 42 static final AndroidKeyStoreLocalImpl sLocalKeyStore = new AndroidKeyStoreLo
calImpl(); |
| 43 static AndroidKeyStoreRemote sRemoteKeyStore; |
| 44 |
| 45 public static void setRemoteKeyStore(AndroidKeyStoreRemote remoteStore) { |
| 46 sRemoteKeyStore = remoteStore; |
| 47 } |
| 48 |
| 40 /** | 49 /** |
| 41 * Common implementation for anynchronous task of handling the certificate r
equest. This | 50 * Common implementation for anynchronous task of handling the certificate r
equest. This |
| 42 * AsyncTask uses the abstract methods to retrieve the authentication materi
al from a | 51 * AsyncTask uses the abstract methods to retrieve the authentication materi
al from a |
| 43 * generalized key store. The key store is accessed in background, as the AP
Is being exercised | 52 * generalized key store. The key store is accessed in background, as the AP
Is being exercised |
| 44 * may be blocking. The results are posted back to native on the UI thread. | 53 * may be blocking. The results are posted back to native on the UI thread. |
| 45 */ | 54 */ |
| 46 abstract static class CertAsyncTask extends AsyncTask<Void, Void, Void> { | 55 abstract static class CertAsyncTask extends AsyncTask<Void, Void, Void> { |
| 47 // These fields will store the results computed in doInBackground so tha
t they can be posted | 56 // These fields will store the results computed in doInBackground so tha
t they can be posted |
| 48 // back in onPostExecute. | 57 // back in onPostExecute. |
| 49 private byte[][] mEncodedChain; | 58 private byte[][] mEncodedChain; |
| 50 private PrivateKey mPrivateKey; | 59 private AndroidPrivateKey mAndroidKey; |
| 51 | 60 |
| 52 // Pointer to the native certificate request needed to return the result
s. | 61 // Pointer to the native certificate request needed to return the result
s. |
| 53 private final int mNativePtr; | 62 private final int mNativePtr; |
| 54 | 63 |
| 55 CertAsyncTask(int nativePtr) { | 64 CertAsyncTask(int nativePtr) { |
| 56 mNativePtr = nativePtr; | 65 mNativePtr = nativePtr; |
| 57 } | 66 } |
| 58 | 67 |
| 59 // These overriden methods will be used to access the key store. | 68 // These overriden methods will be used to access the key store. |
| 60 abstract String getAlias(); | 69 abstract String getAlias(); |
| 61 abstract PrivateKey getPrivateKey(String alias); | 70 abstract AndroidPrivateKey getPrivateKey(String alias); |
| 62 abstract X509Certificate[] getCertificateChain(String alias); | 71 abstract X509Certificate[] getCertificateChain(String alias); |
| 63 | 72 |
| 64 @Override | 73 @Override |
| 65 protected Void doInBackground(Void... params) { | 74 protected Void doInBackground(Void... params) { |
| 66 String alias = getAlias(); | 75 String alias = getAlias(); |
| 67 if (alias == null) return null; | 76 if (alias == null) return null; |
| 68 | 77 |
| 69 PrivateKey key = getPrivateKey(alias); | 78 AndroidPrivateKey key = getPrivateKey(alias); |
| 79 Log.d(TAG, "got key " + key); |
| 70 X509Certificate[] chain = getCertificateChain(alias); | 80 X509Certificate[] chain = getCertificateChain(alias); |
| 81 Log.d(TAG, "got chain " + chain); |
| 82 |
| 71 if (key == null || chain == null || chain.length == 0) { | 83 if (key == null || chain == null || chain.length == 0) { |
| 72 Log.w(TAG, "Empty client certificate chain?"); | 84 Log.w(TAG, "Empty client certificate chain?"); |
| 73 return null; | 85 return null; |
| 74 } | 86 } |
| 75 | 87 |
| 76 // Encode the certificate chain. | 88 // Encode the certificate chain. |
| 77 byte[][] encodedChain = new byte[chain.length][]; | 89 byte[][] encodedChain = new byte[chain.length][]; |
| 78 try { | 90 try { |
| 79 for (int i = 0; i < chain.length; ++i) { | 91 for (int i = 0; i < chain.length; ++i) { |
| 80 encodedChain[i] = chain[i].getEncoded(); | 92 encodedChain[i] = chain[i].getEncoded(); |
| 81 } | 93 } |
| 82 } catch (CertificateEncodingException e) { | 94 } catch (CertificateEncodingException e) { |
| 83 Log.w(TAG, "Could not retrieve encoded certificate chain: " + e)
; | 95 Log.w(TAG, "Could not retrieve encoded certificate chain: " + e)
; |
| 84 return null; | 96 return null; |
| 85 } | 97 } |
| 86 | 98 |
| 87 mEncodedChain = encodedChain; | 99 mEncodedChain = encodedChain; |
| 88 mPrivateKey = key; | 100 mAndroidKey = key; |
| 89 return null; | 101 return null; |
| 90 } | 102 } |
| 91 | 103 |
| 92 @Override | 104 @Override |
| 93 protected void onPostExecute(Void result) { | 105 protected void onPostExecute(Void result) { |
| 94 ThreadUtils.assertOnUiThread(); | 106 ThreadUtils.assertOnUiThread(); |
| 95 nativeOnSystemRequestCompletion(mNativePtr, mEncodedChain, mPrivateK
ey); | 107 nativeOnSystemRequestCompletion(mNativePtr, mEncodedChain, mAndroidK
ey); |
| 96 } | 108 } |
| 97 } | 109 } |
| 98 | 110 |
| 99 /** Implementation of CertAsyncTask for the system KeyChain API. */ | 111 /** Implementation of CertAsyncTask for the system KeyChain API. */ |
| 100 private static class CertAsyncTaskKeyChain extends CertAsyncTask { | 112 private static class CertAsyncTaskKeyChain extends CertAsyncTask { |
| 101 final Context mContext; | 113 final Context mContext; |
| 102 final String mAlias; | 114 final String mAlias; |
| 103 | 115 |
| 104 CertAsyncTaskKeyChain(Context context, int nativePtr, String alias) { | 116 CertAsyncTaskKeyChain(Context context, int nativePtr, String alias) { |
| 105 super(nativePtr); | 117 super(nativePtr); |
| 106 mContext = context; | 118 mContext = context; |
| 107 assert alias != null; | 119 assert alias != null; |
| 108 mAlias = alias; | 120 mAlias = alias; |
| 109 } | 121 } |
| 110 | 122 |
| 111 @Override | 123 @Override |
| 112 String getAlias() { | 124 String getAlias() { |
| 113 return mAlias; | 125 return mAlias; |
| 114 } | 126 } |
| 115 | 127 |
| 116 @Override | 128 @Override |
| 117 PrivateKey getPrivateKey(String alias) { | 129 AndroidPrivateKey getPrivateKey(String alias) { |
| 118 try { | 130 try { |
| 119 return KeyChain.getPrivateKey(mContext, alias); | 131 return sLocalKeyStore.createKey(KeyChain.getPrivateKey(mContext,
alias)); |
| 120 } catch (KeyChainException e) { | 132 } catch (KeyChainException e) { |
| 121 Log.w(TAG, "KeyChainException when looking for '" + alias + "' c
ertificate"); | 133 Log.w(TAG, "KeyChainException when looking for '" + alias + "' c
ertificate"); |
| 122 return null; | 134 return null; |
| 123 } catch (InterruptedException e) { | 135 } catch (InterruptedException e) { |
| 124 Log.w(TAG, "InterruptedException when looking for '" + alias + "
'certificate"); | 136 Log.w(TAG, "InterruptedException when looking for '" + alias + "
'certificate"); |
| 125 return null; | 137 return null; |
| 126 } | 138 } |
| 127 } | 139 } |
| 128 | 140 |
| 129 @Override | 141 @Override |
| (...skipping 23 matching lines...) Expand all Loading... |
| 153 mPort = port; | 165 mPort = port; |
| 154 mPKCS11AuthManager = pkcs11CardAuthManager; | 166 mPKCS11AuthManager = pkcs11CardAuthManager; |
| 155 } | 167 } |
| 156 | 168 |
| 157 @Override | 169 @Override |
| 158 String getAlias() { | 170 String getAlias() { |
| 159 return mPKCS11AuthManager.getClientCertificateAlias(mHostName, mPort
); | 171 return mPKCS11AuthManager.getClientCertificateAlias(mHostName, mPort
); |
| 160 } | 172 } |
| 161 | 173 |
| 162 @Override | 174 @Override |
| 163 PrivateKey getPrivateKey(String alias) { | 175 AndroidPrivateKey getPrivateKey(String alias) { |
| 164 return mPKCS11AuthManager.getPrivateKey(alias); | 176 assert sRemoteKeyStore != null : |
| 177 "PKCS11 certificate request issued with no remote key store
set"; |
| 178 return sRemoteKeyStore.createKey(alias); |
| 165 } | 179 } |
| 166 | 180 |
| 167 @Override | 181 @Override |
| 168 X509Certificate[] getCertificateChain(String alias) { | 182 X509Certificate[] getCertificateChain(String alias) { |
| 169 return mPKCS11AuthManager.getCertificateChain(alias); | 183 return mPKCS11AuthManager.getCertificateChain(alias); |
| 170 } | 184 } |
| 171 } | 185 } |
| 172 | 186 |
| 173 /** | 187 /** |
| 174 * The system KeyChain API will call us back on the alias() method, passing
the alias of the | 188 * The system KeyChain API will call us back on the alias() method, passing
the alias of the |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 // Smart card support is not available, use the system store uncondi
tionally. | 297 // Smart card support is not available, use the system store uncondi
tionally. |
| 284 useSystemStore.run(); | 298 useSystemStore.run(); |
| 285 } | 299 } |
| 286 | 300 |
| 287 // We've taken ownership of the native ssl request object. | 301 // We've taken ownership of the native ssl request object. |
| 288 return true; | 302 return true; |
| 289 } | 303 } |
| 290 | 304 |
| 291 // Called to pass request results to native side. | 305 // Called to pass request results to native side. |
| 292 private static native void nativeOnSystemRequestCompletion( | 306 private static native void nativeOnSystemRequestCompletion( |
| 293 int requestPtr, byte[][] certChain, PrivateKey privateKey); | 307 int requestPtr, byte[][] certChain, AndroidPrivateKey androidKey); |
| 294 } | 308 } |
| OLD | NEW |