diff options
-rw-r--r-- | android_webview/java/src/org/chromium/android_webview/AwTokenBindingManager.java | 51 | ||||
-rw-r--r-- | android_webview/native/token_binding_manager_bridge.cc | 27 |
2 files changed, 71 insertions, 7 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwTokenBindingManager.java b/android_webview/java/src/org/chromium/android_webview/AwTokenBindingManager.java index 3f2f695..a622781 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwTokenBindingManager.java +++ b/android_webview/java/src/org/chromium/android_webview/AwTokenBindingManager.java @@ -7,11 +7,27 @@ package org.chromium.android_webview; import android.net.Uri; import android.webkit.ValueCallback; +import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; import java.security.KeyPair; -import java.security.spec.AlgorithmParameterSpec; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; + +import javax.crypto.Cipher; +import javax.crypto.EncryptedPrivateKeyInfo; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; /** * AwTokenBindingManager manages the token binding protocol. @@ -25,11 +41,16 @@ import java.security.spec.AlgorithmParameterSpec; */ @JNINamespace("android_webview") public final class AwTokenBindingManager { + private static final String TAG = "TokenBindingManager"; + private static final String PASSWORD = ""; + private static final String ALGORITHM = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"; + private static final String ELLIPTIC_CURVE = "EC"; + public void enableTokenBinding() { nativeEnableTokenBinding(); } - public void getKey(Uri origin, AlgorithmParameterSpec[] spec, ValueCallback<KeyPair> callback) { + public void getKey(Uri origin, String[] spec, ValueCallback<KeyPair> callback) { if (callback == null) { throw new IllegalArgumentException("callback can't be null"); } @@ -50,8 +71,30 @@ public final class AwTokenBindingManager { } @CalledByNative - private static void onKeyReady(ValueCallback<KeyPair> callback) { - callback.onReceiveValue(null); + private static void onKeyReady( + ValueCallback<KeyPair> callback, byte[] privateKeyBytes, byte[] publicKeyBytes) { + if (privateKeyBytes == null || publicKeyBytes == null) { + callback.onReceiveValue(null); + return; + } + KeyPair keyPair = null; + try { + EncryptedPrivateKeyInfo epkInfo = new EncryptedPrivateKeyInfo(privateKeyBytes); + SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM); + Key key = secretKeyFactory.generateSecret(new PBEKeySpec(PASSWORD.toCharArray())); + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, key, epkInfo.getAlgParameters()); + KeyFactory factory = KeyFactory.getInstance(ELLIPTIC_CURVE); + PrivateKey privateKey = factory.generatePrivate(epkInfo.getKeySpec(cipher)); + PublicKey publicKey = + factory.generatePublic(new X509EncodedKeySpec(publicKeyBytes)); + keyPair = new KeyPair(publicKey, privateKey); + } catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException + | NoSuchPaddingException | InvalidKeyException + | InvalidAlgorithmParameterException ex) { + Log.e(TAG, "Failed converting key ", ex); + } + callback.onReceiveValue(keyPair); } @CalledByNative diff --git a/android_webview/native/token_binding_manager_bridge.cc b/android_webview/native/token_binding_manager_bridge.cc index 07c690f..cf959f5 100644 --- a/android_webview/native/token_binding_manager_bridge.cc +++ b/android_webview/native/token_binding_manager_bridge.cc @@ -6,15 +6,19 @@ #include "android_webview/browser/net/token_binding_manager.h" #include "base/android/jni_android.h" +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/bind.h" #include "content/public/browser/browser_thread.h" #include "crypto/ec_private_key.h" #include "jni/AwTokenBindingManager_jni.h" +#include "net/base/net_errors.h" +#include "net/ssl/channel_id_service.h" using base::android::ConvertJavaStringToUTF8; using base::android::ScopedJavaGlobalRef; using content::BrowserThread; +using net::ChannelIDService; namespace android_webview { @@ -26,10 +30,27 @@ void OnKeyReady(const ScopedJavaGlobalRef<jobject>& callback, crypto::ECPrivateKey* key) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - // TODO(sgurun) implement conversion and plumbing the keypair to java. - JNIEnv* env = base::android::AttachCurrentThread(); - Java_AwTokenBindingManager_onKeyReady(env, callback.obj()); + + if (status != net::OK || !key) { + Java_AwTokenBindingManager_onKeyReady(env, callback.obj(), nullptr, + nullptr); + return; + } + + std::vector<uint8_t> private_key; + key->ExportEncryptedPrivateKey(ChannelIDService::kEPKIPassword, 1, + &private_key); + ScopedJavaLocalRef<jbyteArray> jprivate_key = base::android::ToJavaByteArray( + env, private_key.data(), private_key.size()); + + std::vector<uint8_t> public_key; + key->ExportPublicKey(&public_key); + ScopedJavaLocalRef<jbyteArray> jpublic_key = base::android::ToJavaByteArray( + env, public_key.data(), public_key.size()); + + Java_AwTokenBindingManager_onKeyReady(env, callback.obj(), jprivate_key.obj(), + jpublic_key.obj()); } // Indicates webview client that key deletion is complete. |