1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "BluetoothKeystoreServiceJni"
18 
19 #include "base/logging.h"
20 #include "com_android_bluetooth.h"
21 #include "hardware/bt_keystore.h"
22 
23 #include <string.h>
24 #include <shared_mutex>
25 
26 using bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks;
27 using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface;
28 
29 namespace android {
30 static jmethodID method_setEncryptKeyOrRemoveKeyCallback;
31 static jmethodID method_getKeyCallback;
32 
33 static BluetoothKeystoreInterface* sBluetoothKeystoreInterface = nullptr;
34 static std::shared_timed_mutex interface_mutex;
35 
36 static jobject mCallbacksObj = nullptr;
37 static std::shared_timed_mutex callbacks_mutex;
38 
39 class BluetoothKeystoreCallbacksImpl
40     : public bluetooth::bluetooth_keystore::BluetoothKeystoreCallbacks {
41  public:
42   ~BluetoothKeystoreCallbacksImpl() = default;
43 
set_encrypt_key_or_remove_key(const std::string prefixString,const std::string decryptedString)44   void set_encrypt_key_or_remove_key(
45       const std::string prefixString,
46       const std::string decryptedString) override {
47     LOG(INFO) << __func__;
48 
49     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
50     CallbackEnv sCallbackEnv(__func__);
51     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
52 
53     jstring j_prefixString = sCallbackEnv->NewStringUTF(prefixString.c_str());
54     jstring j_decryptedString =
55         sCallbackEnv->NewStringUTF(decryptedString.c_str());
56 
57     sCallbackEnv->CallVoidMethod(mCallbacksObj,
58                                  method_setEncryptKeyOrRemoveKeyCallback,
59                                  j_prefixString, j_decryptedString);
60   }
61 
get_key(const std::string prefixString)62   std::string get_key(const std::string prefixString) override {
63     LOG(INFO) << __func__;
64 
65     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
66     CallbackEnv sCallbackEnv(__func__);
67     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return "";
68 
69     jstring j_prefixString = sCallbackEnv->NewStringUTF(prefixString.c_str());
70 
71     jstring j_decrypt_str = (jstring)sCallbackEnv->CallObjectMethod(
72         mCallbacksObj, method_getKeyCallback, j_prefixString);
73 
74     if (j_decrypt_str == nullptr) {
75       ALOGE("%s: Got a null decrypt_str", __func__);
76       return "";
77     }
78 
79     const char* value = sCallbackEnv->GetStringUTFChars(j_decrypt_str, nullptr);
80     std::string ret(value);
81     sCallbackEnv->ReleaseStringUTFChars(j_decrypt_str, value);
82 
83     return ret;
84   }
85 };
86 
87 static BluetoothKeystoreCallbacksImpl sBluetoothKeystoreCallbacks;
88 
classInitNative(JNIEnv * env,jclass clazz)89 static void classInitNative(JNIEnv* env, jclass clazz) {
90   method_setEncryptKeyOrRemoveKeyCallback =
91       env->GetMethodID(clazz, "setEncryptKeyOrRemoveKeyCallback",
92                        "(Ljava/lang/String;Ljava/lang/String;)V");
93 
94   method_getKeyCallback = env->GetMethodID(
95       clazz, "getKeyCallback", "(Ljava/lang/String;)Ljava/lang/String;");
96 
97   LOG(INFO) << __func__ << ": succeeds";
98 }
99 
initNative(JNIEnv * env,jobject object)100 static void initNative(JNIEnv* env, jobject object) {
101   std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
102   std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
103 
104   const bt_interface_t* btInf = getBluetoothInterface();
105   if (btInf == nullptr) {
106     LOG(ERROR) << "Bluetooth module is not loaded";
107     return;
108   }
109 
110   if (sBluetoothKeystoreInterface != nullptr) {
111     LOG(INFO)
112         << "Cleaning up BluetoothKeystore Interface before initializing...";
113     sBluetoothKeystoreInterface = nullptr;
114   }
115 
116   if (mCallbacksObj != nullptr) {
117     LOG(INFO) << "Cleaning up BluetoothKeystore callback object";
118     env->DeleteGlobalRef(mCallbacksObj);
119     mCallbacksObj = nullptr;
120   }
121 
122   if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
123     LOG(ERROR)
124         << "Failed to allocate Global Ref for BluetoothKeystore Callbacks";
125     return;
126   }
127 
128   sBluetoothKeystoreInterface =
129       (BluetoothKeystoreInterface*)btInf->get_profile_interface(BT_KEYSTORE_ID);
130   if (sBluetoothKeystoreInterface == nullptr) {
131     LOG(ERROR) << "Failed to get BluetoothKeystore Interface";
132     return;
133   }
134 
135   sBluetoothKeystoreInterface->init(&sBluetoothKeystoreCallbacks);
136 }
137 
cleanupNative(JNIEnv * env,jobject object)138 static void cleanupNative(JNIEnv* env, jobject object) {
139   std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
140   std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
141 
142   const bt_interface_t* btInf = getBluetoothInterface();
143   if (btInf == nullptr) {
144     LOG(ERROR) << "Bluetooth module is not loaded";
145     return;
146   }
147 
148   if (sBluetoothKeystoreInterface != nullptr) {
149     sBluetoothKeystoreInterface = nullptr;
150   }
151 
152   if (mCallbacksObj != nullptr) {
153     env->DeleteGlobalRef(mCallbacksObj);
154     mCallbacksObj = nullptr;
155   }
156 }
157 
158 static JNINativeMethod sMethods[] = {
159     {"classInitNative", "()V", (void*)classInitNative},
160     {"initNative", "()V", (void*)initNative},
161     {"cleanupNative", "()V", (void*)cleanupNative},
162 };
163 
register_com_android_bluetooth_btservice_BluetoothKeystore(JNIEnv * env)164 int register_com_android_bluetooth_btservice_BluetoothKeystore(JNIEnv* env) {
165   return jniRegisterNativeMethods(
166       env,
167       "com/android/bluetooth/btservice/bluetoothkeystore/"
168       "BluetoothKeystoreNativeInterface",
169       sMethods, NELEM(sMethods));
170 }
171 }  // namespace android
172