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

Commit 9a3fcfec authored by weichinweng's avatar weichinweng Committed by Automerger Merge Worker
Browse files

NIAP: implement bluetooth keystore interface.(1/2) am: 4feda407

Change-Id: Ie57a62fead5ec90ec2dc4a934151edf052d0b566
parents 12095d76 4feda407
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -153,6 +153,8 @@ int register_com_android_bluetooth_gatt (JNIEnv* env);
int register_com_android_bluetooth_sdp (JNIEnv* env);

int register_com_android_bluetooth_hearing_aid(JNIEnv* env);

int register_com_android_bluetooth_btservice_BluetoothKeystore(JNIEnv* env);
}

#endif /* COM_ANDROID_BLUETOOTH_H */
+7 −0
Original line number Diff line number Diff line
@@ -1377,6 +1377,13 @@ jint JNI_OnLoad(JavaVM* jvm, void* reserved) {
    return JNI_ERR;
  }

  status =
      android::register_com_android_bluetooth_btservice_BluetoothKeystore(e);
  if (status < 0) {
    ALOGE("jni BluetoothKeyStore registration failure: %d", status);
    return JNI_ERR;
  }

  status = android::register_com_android_bluetooth_hfp(e);
  if (status < 0) {
    ALOGE("jni hfp registration failure, status: %d", status);
+171 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "BluetoothKeystoreServiceJni"

#include "base/logging.h"
#include "com_android_bluetooth.h"
#include "hardware/bt_keystore.h"

#include <string.h>
#include <shared_mutex>

using bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks;
using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface;

namespace android {
static jmethodID method_setEncryptKeyOrRemoveKeyCallback;
static jmethodID method_getKeyCallback;

static BluetoothKeystoreInterface* sBluetoothKeystoreInterface = nullptr;
static std::shared_timed_mutex interface_mutex;

static jobject mCallbacksObj = nullptr;
static std::shared_timed_mutex callbacks_mutex;

class BluetoothKeystoreCallbacksImpl
    : public bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks {
 public:
  ~BluetoothKeystoreCallbacksImpl() = default;

  void set_encrypt_key_or_remove_key(
      const std::string prefixString,
      const std::string decryptedString) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
    CallbackEnv sCallbackEnv(__func__);
    if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;

    jstring j_prefixString = sCallbackEnv->NewStringUTF(prefixString.c_str());
    jstring j_decryptedString =
        sCallbackEnv->NewStringUTF(decryptedString.c_str());

    sCallbackEnv->CallVoidMethod(mCallbacksObj,
                                 method_setEncryptKeyOrRemoveKeyCallback,
                                 j_prefixString, j_decryptedString);
  }

  std::string get_key(const std::string prefixString) override {
    LOG(INFO) << __func__;

    std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
    CallbackEnv sCallbackEnv(__func__);
    if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return "";

    jstring j_prefixString = sCallbackEnv->NewStringUTF(prefixString.c_str());

    jstring j_decrypt_str = (jstring)sCallbackEnv->CallObjectMethod(
        mCallbacksObj, method_getKeyCallback, j_prefixString);

    if (j_decrypt_str == nullptr) {
      ALOGE("%s: Got a null decrypt_str", __func__);
      return "";
    }

    const char* value = sCallbackEnv->GetStringUTFChars(j_decrypt_str, nullptr);
    std::string ret(value);
    sCallbackEnv->ReleaseStringUTFChars(j_decrypt_str, value);

    return ret;
  }
};

static BluetoothKeystoreCallbacksImpl sBluetoothKeystoreCallbacks;

static void classInitNative(JNIEnv* env, jclass clazz) {
  method_setEncryptKeyOrRemoveKeyCallback =
      env->GetMethodID(clazz, "setEncryptKeyOrRemoveKeyCallback",
                       "(Ljava/lang/String;Ljava/lang/String;)V");

  method_getKeyCallback = env->GetMethodID(
      clazz, "getKeyCallback", "(Ljava/lang/String;)Ljava/lang/String;");

  LOG(INFO) << __func__ << ": succeeds";
}

static void initNative(JNIEnv* env, jobject object) {
  std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
  std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);

  const bt_interface_t* btInf = getBluetoothInterface();
  if (btInf == nullptr) {
    LOG(ERROR) << "Bluetooth module is not loaded";
    return;
  }

  if (sBluetoothKeystoreInterface != nullptr) {
    LOG(INFO)
        << "Cleaning up BluetoothKeystore Interface before initializing...";
    sBluetoothKeystoreInterface = nullptr;
  }

  if (mCallbacksObj != nullptr) {
    LOG(INFO) << "Cleaning up BluetoothKeystore callback object";
    env->DeleteGlobalRef(mCallbacksObj);
    mCallbacksObj = nullptr;
  }

  if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
    LOG(ERROR)
        << "Failed to allocate Global Ref for BluetoothKeystore Callbacks";
    return;
  }

  sBluetoothKeystoreInterface =
      (BluetoothKeystoreInterface*)btInf->get_profile_interface(BT_KEYSTORE_ID);
  if (sBluetoothKeystoreInterface == nullptr) {
    LOG(ERROR) << "Failed to get BluetoothKeystore Interface";
    return;
  }

  sBluetoothKeystoreInterface->init(&sBluetoothKeystoreCallbacks);
}

static void cleanupNative(JNIEnv* env, jobject object) {
  std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
  std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);

  const bt_interface_t* btInf = getBluetoothInterface();
  if (btInf == nullptr) {
    LOG(ERROR) << "Bluetooth module is not loaded";
    return;
  }

  if (sBluetoothKeystoreInterface != nullptr) {
    sBluetoothKeystoreInterface = nullptr;
  }

  if (mCallbacksObj != nullptr) {
    env->DeleteGlobalRef(mCallbacksObj);
    mCallbacksObj = nullptr;
  }
}

static JNINativeMethod sMethods[] = {
    {"classInitNative", "()V", (void*)classInitNative},
    {"initNative", "()V", (void*)initNative},
    {"cleanupNative", "()V", (void*)cleanupNative},
};

int register_com_android_bluetooth_btservice_BluetoothKeystore(JNIEnv* env) {
  return jniRegisterNativeMethods(
      env,
      "com/android/bluetooth/btservice/bluetoothkeystore/"
      "BluetoothKeystoreNativeInterface",
      sMethods, NELEM(sMethods));
}
}  // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -453,6 +453,8 @@ public class AdapterService extends Service {
        mBatteryStats = IBatteryStats.Stub.asInterface(
                ServiceManager.getService(BatteryStats.SERVICE_NAME));

        mBluetoothKeystoreService.initJni();

        mSdpManager = SdpManager.init(this);
        registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP));

+104 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bluetooth.btservice.bluetoothkeystore;

import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;

final class BluetoothKeystoreNativeInterface {

    private static final String TAG = "BluetoothKeystoreNativeInterface";

    @GuardedBy("INSTANCE_LOCK")
    private static BluetoothKeystoreNativeInterface sInstance;
    private static final Object INSTANCE_LOCK = new Object();

    static {
        classInitNative();
    }

    private BluetoothKeystoreNativeInterface() {
    }

    /**
     * Get singleton instance.
     */
    public static BluetoothKeystoreNativeInterface getInstance() {
        synchronized (INSTANCE_LOCK) {
            if (sInstance == null) {
                sInstance = new BluetoothKeystoreNativeInterface();
            }
            return sInstance;
        }
    }

    /**
     * Initializes the native interface.
     *
     * priorities to configure.
     */
    public void init() {
        initNative();
    }

    /**
     * Cleanup the native interface.
     */
    public void cleanup() {
        cleanupNative();
    }

    // Callbacks from the native stack back into the Java framework.
    // All callbacks are routed via the Service which will disambiguate which
    // state machine the message should be routed to.

    private void setEncryptKeyOrRemoveKeyCallback(String prefixString, String decryptedString) {
        BluetoothKeystoreService service = BluetoothKeystoreService.getBluetoothKeystoreService();
        if (service != null) {
            try {
                service.setEncryptKeyOrRemoveKey(prefixString, decryptedString);
            } catch (InterruptedException e) {
                Log.e(TAG, "Interrupted while operating.");
            } catch (IOException e) {
                Log.e(TAG, "IO error while file operating.");
            } catch (NoSuchAlgorithmException e) {
                Log.e(TAG, "encrypt could not find the algorithm: SHA256");
            }
        } else {
            Log.e(TAG, "Event ignored, service not available: " + prefixString);
        }
    }

    private String getKeyCallback(String prefixString) {
        BluetoothKeystoreService service = BluetoothKeystoreService.getBluetoothKeystoreService();
        if (service != null) {
            return service.getKey(prefixString);
        } else {
            Log.e(TAG, "Event ignored, service not available: " + prefixString);
            return null;
        }
    }

    // Native methods that call into the JNI interface
    private static native void classInitNative();
    private native void initNative();
    private native void cleanupNative();
}
Loading