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