Merge "persist: add the default numbers property array and random number generation"
diff --git a/Makefile b/Makefile
index 8fd9dba..b087d4c 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
CFLAGS = -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -g -I. -DEXECUTABLE
-CPPFLAGS = -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -g -I. -DEXECUTABLE -D_UNITTEST_
+CPPFLAGS = -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -g -I. -DEXECUTABLE -D_UNITTEST_ -DPREF_PATH=\"/tmp/bt.newblue.prefs\"
TEST := new_blue_test
@@ -36,7 +36,9 @@
$(CC) $(CFLAGS) -o $@ -g $(OBJ) $(OBJ_TEST) -ldl -lpthread -lrt
OBJ_UNITTEST = \
- tests/sm_unittest.o
+ tests/unittest.o \
+ tests/sm_unittest.o \
+ tests/persist_unittest.o
new_blue_unittest: $(OBJ_UNITTEST) $(OBJ)
$(CXX) $(CPPFLAGS) -o $@ $^ -lgtest -ldl -lpthread
diff --git a/config.h b/config.h
index c14a513..09ba579 100644
--- a/config.h
+++ b/config.h
@@ -1,3 +1,8 @@
+/*
+ * Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
#ifndef _CONFIG_H_
#define _CONFIG_H_
@@ -35,11 +40,13 @@
/*
* Where to store stack config/state
*/
+#ifndef PREF_PATH
#ifdef ANDROID
#define PREF_PATH "/data/data/com.android.bluetooth/bt.newblue.prefs"
#else
#define PREF_PATH "bt.newblue.prefs"
#endif
+#endif
/*
* AAPI will try to queue this much per socket before shutting off flow
diff --git a/persist.c b/persist.c
index df0bc37..5b17ac1 100644
--- a/persist.c
+++ b/persist.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
@@ -87,6 +92,8 @@
/* fwd decls */
static bool persistPropListLoad(struct persistProp **headP, struct persistProp **tailP, int fd, uint64_t len);
static bool persistSetPropInList(struct persistProp **headP, struct persistProp **tailP, uint32_t name, uint32_t type, const void *buf, uint32_t len, bool replaceExisting);
+static bool persistAddNumber(struct persistProp **headP, struct persistProp **tailP, uint8_t numType, uint64_t num);
+static struct persistProp* persistFindNum(struct persistProp *head, uint8_t numType);
/*
* FUNCTION: persistGetRealtime
@@ -446,6 +453,48 @@
}
/*
+ * FUNCTION: persistGenRandomBytes
+ * USE: Generate random bytes
+ * PARAMS: out - where the random bytes are stored
+ * len - the size of desired length of random bytes
+ * RETURN: success with the valid output
+ * NOTES:
+ */
+static bool persistGenRandomBytes(uint8_t *out, uint8_t len)
+{
+ int fd;
+ bool ret;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1) {
+ logw("Failed to open urandom\n");
+ return false;
+ }
+
+ ret = r_read(fd, out, len);
+ close(fd);
+
+ if (!ret) {
+ logw("Failed to read urandom\n");
+ return false;
+ }
+ return true;
+}
+
+/*
+ * FUNCTION: persistGenRand
+ * USE: Generate a random 64-bit number
+ * PARAMS: out - where the random number is be stored
+ * RETURN: success with the valid output
+ * NOTES:
+ */
+static bool persistGenRand(uint64_t *out) {
+ if (!out)
+ return false;
+ return persistGenRandomBytes((uint8_t *)out, sizeof(*out));
+}
+
+/*
* FUNCTION: persistAddKey
* USE: Add a key of the given type and add it to the given list (and optionally generate it)
* PARAMS: headP - list head stored here
@@ -458,27 +507,14 @@
static bool persistAddKey(struct persistProp **headP, struct persistProp **tailP, uint8_t keyType, const uint8_t *key)
{
struct persistKey pkey;
- bool ret;
- int fd;
pkey.keyType = keyType;
if (key)
memcpy(pkey.key, key, sizeof(pkey.key));
else {
- fd = open("/dev/urandom", O_RDONLY);
- if (fd == -1) {
- logw("Failed to open urandom\n");
+ if (!persistGenRandomBytes(pkey.key, HCI_LE_KEY_LEN))
return false;
- }
-
- ret = r_read(fd, pkey.key, sizeof(pkey.key));
- close(fd);
-
- if (!ret) {
- logw("Failed to read urandom\n");
- return false;
- }
}
return persistSetPropInList(headP, tailP, PERS_NAME_KEY, PERS_TYPE_BYTE_ARRAY, &pkey, sizeof(pkey), false);
@@ -494,7 +530,7 @@
static void persistLoadRequiredProps(void)
{
static const char defaultName[] = "NB.t";
- struct persistProp *keylist, *key;
+ struct persistProp *keylist, *key, *numList;
if (!persistPropFind(mPropsHead, PERS_NAME_DEVICE_NAME, PERS_TYPE_BYTE_ARRAY))
if (!persistPropAddByteArr(&mPropsHead, &mPropsTail, PERS_NAME_DEVICE_NAME, strlen(defaultName), defaultName))
@@ -537,6 +573,23 @@
if (!persistAddKey(&keyArr->head, &keyArr->tail, KEY_TYPE_DHK, NULL))
loge("failed to create & store DHK\n");
}
+
+ numList = persistPropFind(mPropsHead, PERS_NAME_NUMBERS, PERS_TYPE_ARRAY);
+ if (!numList)
+ numList = persistPropAddEmptyArray(&mPropsHead, &mPropsTail, PERS_NAME_NUMBERS);
+ if (!numList)
+ loge("Failed to add device numbers default prop\n");
+ else {
+ struct persistArrayInRam *numArr = (struct persistArrayInRam*)(numList + 1);
+ uint64_t num = 0;
+
+ if (!persistFindNum(numArr->head, PERSIST_NUM_TYPE_SM_RANDOM)) {
+ if (!persistGenRand(&num))
+ loge("failed to generate SM Random\n");
+ else if (!persistAddNumber(&numArr->head, &numArr->tail, PERSIST_NUM_TYPE_SM_RANDOM, num))
+ loge("failed to create & store SM Random\n");
+ }
+ }
}
/*
@@ -652,7 +705,6 @@
struct persistProp *t;
int fd;
-
pthread_mutex_lock(&mLock);
utilSetBE32(&hdr.magic, PERSIST_MAGIC);
utilSetBE32(&hdr.version, PERSIST_VERSION_CUR);
@@ -1062,7 +1114,7 @@
* FUNCTION: persistGetKnownDev
* USE: Find info given a mac address
* PARAMS: addr - the address to look up
- * name - name gets stored here (shoudl fit at least HCI_DEV_NAME_LEN bytes). may be null
+ * name - name gets stored here (should fit at least HCI_DEV_NAME_LEN bytes). may be null
* nameLen - name's length gets stored here. may be null
* devCls - device class gets stored here. may be null
* RETURN: true if device was found (not a promise that any data was returned)
@@ -1177,7 +1229,7 @@
logw("Failed to save device name\n");
if (haveName) {
- /* never replace an existing name with a shortened one. Always replce with a full one */
+ /* never replace an existing name with a shortened one. Always replace with a full one */
struct persistArrayInRam *devItems;
devItems = (struct persistArrayInRam*)(dev + 1);
@@ -1196,6 +1248,10 @@
if (!persistPropAddEmptyArray(&devArr->head, &devArr->tail, PERS_NAME_KEYS))
logw("Failed to add the missing keys container to device\n");
+ if (!persistPropFind(devArr->head, PERS_NAME_NUMBERS, PERS_TYPE_ARRAY))
+ if (!persistPropAddEmptyArray(&devArr->head, &devArr->tail, PERS_NAME_NUMBERS))
+ logw("Failed to add the missing numbers container to device\n");
+
out:
return dev;
}
diff --git a/persist.h b/persist.h
index f72c5fa..e38b9f4 100644
--- a/persist.h
+++ b/persist.h
@@ -1,3 +1,8 @@
+/*
+ * Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
#ifndef _PERSIST_H_
#define _PERSIST_H_
@@ -39,8 +44,8 @@
bool persistGetDevKey(const struct bt_addr *addr, uint8_t keyType, uint8_t *key); //addr = NULL for our own keys, all keys are HCI_LINK_KEY_LEN bytes long
bool persistDelDevKeys(const struct bt_addr *addr); //addr = NULL for our own keys, all keys are HCI_LINK_KEY_LEN bytes long
-bool persistAddDevNumber(const struct bt_addr *addr, uint8_t numType, uint64_t num); //addr = NULL for our own numbers
-bool persistGetDevNumber(const struct bt_addr *addr, uint8_t keyType, uint64_t *num); //addr = NULL for our own numbers
+bool persistAddDevNumber(const struct bt_addr *addr, uint8_t numType, uint64_t num); //addr = NULL for our own numbers
+bool persistGetDevNumber(const struct bt_addr *addr, uint8_t numType, uint64_t *num); //addr = NULL for our own numbers
bool persistDelDevNumbers(const struct bt_addr *addr); //addr = NULL for our own numbers
diff --git a/tests/persist_unittest.cc b/tests/persist_unittest.cc
new file mode 100644
index 0000000..4abd387
--- /dev/null
+++ b/tests/persist_unittest.cc
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <string.h>
+
+#include <gtest/gtest.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "../hci.h"
+#include "../persist.h"
+
+#if defined(__cplusplus)
+}
+#endif
+
+namespace {
+
+class PersistTestSuite: public testing::Test {
+ public:
+ const struct bt_addr *getDevOneAddr() { return &devOneAddr; }
+ const struct bt_addr *getDevTwoAddr() { return &devTwoAddr; }
+ std::string getDevOneName() { return devOneName; }
+ std::string getDevTwoName() { return devTwoName; }
+
+ protected:
+ virtual void SetUp() {
+ int addrOne[BT_MAC_LEN] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+ int addrTwo[BT_MAC_LEN] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
+ uint32_t nameOneLen = devOneName.size() + 1;
+ uint32_t nameTwoLen = devTwoName.size() + 1;
+
+ persistLoad();
+
+ devOneName = "Name of DevOne";
+ devTwoName = "Name of DevTwo";
+ devOneAddr.type = BT_ADDR_TYPE_LE_RANDOM;
+ memcpy(devOneAddr.addr, addrOne, sizeof(devOneAddr.addr));
+ devTwoAddr.type = BT_ADDR_TYPE_LE_RANDOM;
+ memcpy(devTwoAddr.addr, addrTwo, sizeof(devTwoAddr.addr));
+
+ persistAddKnownDev(&devOneAddr, devOneName.c_str(), &nameOneLen, true, NULL);
+ persistAddKnownDev(&devTwoAddr, devTwoName.c_str(), &nameTwoLen, true, NULL);
+ }
+ virtual void TearDown() {
+ unlink(PREF_PATH);
+ }
+
+ private:
+ std::string devOneName;
+ std::string devTwoName;
+ struct bt_addr devOneAddr;
+ struct bt_addr devTwoAddr;
+};
+
+TEST_F(PersistTestSuite, LocalDeviceNameGetSet) {
+ char myDevName[] = "My Dev Name";
+ char myLongDevName[] = "\
+ My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name \
+ My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name \
+ My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name My Dev Name \
+ My Dev Name My Dev Name";
+ char name[HCI_DEV_NAME_LEN];
+
+ // default name
+ ASSERT_EQ(persistGetDeviceName(name), strlen("NB.t"));
+ ASSERT_EQ(strncmp(name, "NB.t", strlen("NB.t")), 0);
+
+ // normal name
+ persistSetDeviceName(myDevName, sizeof(myDevName));
+ ASSERT_EQ(persistGetDeviceName(name), sizeof(myDevName));
+ ASSERT_EQ(strncmp(name, myDevName, sizeof(myDevName)), 0);
+
+ // long name
+ persistSetDeviceName(myLongDevName, sizeof(myLongDevName));
+ ASSERT_EQ(persistGetDeviceName(name), HCI_DEV_NAME_LEN);
+ ASSERT_EQ(strncmp(name, myLongDevName, HCI_DEV_NAME_LEN), 0);
+
+ // no name
+ persistSetDeviceName("", 0);
+ ASSERT_EQ(persistGetDeviceName(name), 0);
+}
+
+TEST_F(PersistTestSuite, LocalDiscoveryGetSet) {
+ // default discovery length
+ ASSERT_EQ(persistGetDiscoveryLength(), 60);
+
+ ASSERT_TRUE(persistSetDiscoveryLength(100));
+ ASSERT_EQ(persistGetDiscoveryLength(), 100);
+}
+
+TEST_F(PersistTestSuite, DeviceGetAddDel) {
+ char name[HCI_DEV_NAME_LEN];
+ uint32_t nameLen = 0;
+ uint32_t devCls = 0;
+
+ ASSERT_TRUE(persistGetKnownDev(getDevOneAddr(), name, &nameLen, NULL));
+ ASSERT_EQ(strncmp(name, getDevOneName().c_str(), nameLen), 0);
+
+ // delete device two
+ persistDelKnownDev(getDevTwoAddr());
+ ASSERT_FALSE(persistGetKnownDev(getDevTwoAddr(), name, &nameLen, NULL));
+
+ // add device one back
+ nameLen = getDevTwoName().size() + 1;
+ persistAddKnownDev(getDevTwoAddr(), getDevTwoName().c_str(), &nameLen, true, NULL);
+ ASSERT_TRUE(persistGetKnownDev(getDevTwoAddr(), name, &nameLen, NULL));
+ ASSERT_EQ(strncmp(name, getDevTwoName().c_str(), nameLen), 0);
+}
+
+TEST_F(PersistTestSuite, DeviceKeyGetAddDel) {
+ uint8_t keyDHK[HCI_LE_KEY_LEN] = {0x4C, 0x68, 0x38, 0x41, 0x39, 0xF5, 0x74, 0xD8,
+ 0x36, 0xBC, 0xF3, 0x4E, 0x9D, 0xFB, 0x01, 0xBF,};
+ uint8_t keyIRK[HCI_LE_KEY_LEN] = {0x57, 0x83, 0xD5, 0x21, 0x56, 0xAD, 0x6F, 0x0E,
+ 0x63, 0x88, 0x27, 0x4E, 0xC6, 0x70, 0x2E, 0xE0,};
+ uint8_t key[HCI_LE_KEY_LEN] = {0,};
+
+ // set IRK key for local device without providing key
+ ASSERT_TRUE(persistGetDevKey(NULL, KEY_TYPE_IRK, key));
+ ASSERT_TRUE(persistAddDevKey(NULL, KEY_TYPE_IRK, NULL));
+ ASSERT_TRUE(persistGetDevKey(NULL, KEY_TYPE_IRK, key));
+ ASSERT_TRUE(persistDelDevKeys(NULL));
+ ASSERT_FALSE(persistGetDevKey(NULL, KEY_TYPE_IRK, key));
+
+ // set IRK and DHK keys for device one
+ ASSERT_FALSE(persistGetDevKey(getDevOneAddr(), KEY_TYPE_IRK, key));
+ ASSERT_TRUE(persistAddDevKey(getDevOneAddr(), KEY_TYPE_IRK, keyIRK));
+ ASSERT_TRUE(persistGetDevKey(getDevOneAddr(), KEY_TYPE_IRK, key));
+ ASSERT_EQ(memcmp(keyIRK, key, HCI_LE_KEY_LEN), 0);
+ ASSERT_TRUE(persistAddDevKey(getDevOneAddr(), KEY_TYPE_DHK, keyDHK));
+ ASSERT_TRUE(persistGetDevKey(getDevOneAddr(), KEY_TYPE_DHK, key));
+ ASSERT_EQ(memcmp(keyDHK, key, HCI_LE_KEY_LEN), 0);
+ ASSERT_TRUE(persistDelDevKeys(getDevOneAddr()));
+ ASSERT_FALSE(persistGetDevKey(getDevOneAddr(), KEY_TYPE_IRK, key));
+ ASSERT_FALSE(persistGetDevKey(getDevOneAddr(), KEY_TYPE_DHK, key));
+
+ // delete device two and try to add/get/delete keys of device two
+ persistDelKnownDev(getDevTwoAddr());
+ ASSERT_FALSE(persistGetDevKey(getDevTwoAddr(), KEY_TYPE_IRK, key));
+ ASSERT_TRUE(persistDelDevKeys(getDevTwoAddr()));
+ ASSERT_TRUE(persistAddDevKey(getDevTwoAddr(), KEY_TYPE_IRK, keyIRK));
+}
+
+TEST_F(PersistTestSuite, DeviceNumerGetAddDel) {
+ uint64_t randNumOne = 12345678;
+ uint64_t randNumTwo = 87654321;
+ uint64_t num = 0;
+
+ // set a number for local device
+ ASSERT_TRUE(persistGetDevNumber(NULL, PERSIST_NUM_TYPE_SM_RANDOM, &num));
+ ASSERT_TRUE(persistAddDevNumber(NULL, PERSIST_NUM_TYPE_SM_RANDOM, randNumOne));
+ ASSERT_TRUE(persistGetDevNumber(NULL, PERSIST_NUM_TYPE_SM_RANDOM, &num));
+ ASSERT_EQ(num, randNumOne);
+
+ // replace the randNumOne with randNumTwo for local device
+ ASSERT_TRUE(persistAddDevNumber(NULL, PERSIST_NUM_TYPE_SM_RANDOM, randNumTwo));
+ ASSERT_TRUE(persistGetDevNumber(NULL, PERSIST_NUM_TYPE_SM_RANDOM, &num));
+ ASSERT_EQ(num, randNumTwo);
+
+ // delete numbers of local device
+ ASSERT_TRUE(persistDelDevNumbers(NULL));
+ ASSERT_FALSE(persistGetDevNumber(NULL, PERSIST_NUM_TYPE_SM_RANDOM, &num));
+
+ // set a number for device one
+ ASSERT_FALSE(persistGetDevNumber(getDevOneAddr(), PERSIST_NUM_TYPE_SM_RANDOM, &num));
+ ASSERT_TRUE(persistAddDevNumber(getDevOneAddr(), PERSIST_NUM_TYPE_SM_RANDOM, randNumOne));
+ ASSERT_TRUE(persistGetDevNumber(getDevOneAddr(), PERSIST_NUM_TYPE_SM_RANDOM, &num));
+ ASSERT_EQ(num, randNumOne);
+
+ // replace the randNumOne with randNumTwo for device one
+ ASSERT_TRUE(persistAddDevNumber(getDevOneAddr(), PERSIST_NUM_TYPE_SM_RANDOM, randNumTwo));
+ ASSERT_TRUE(persistGetDevNumber(getDevOneAddr(), PERSIST_NUM_TYPE_SM_RANDOM, &num));
+ ASSERT_EQ(num, randNumTwo);
+
+ // delete numbers of device one
+ ASSERT_TRUE(persistDelDevNumbers(getDevOneAddr()));
+ ASSERT_FALSE(persistGetDevNumber(getDevOneAddr(), PERSIST_NUM_TYPE_SM_RANDOM, &num));
+
+ // delete device two and try to add/get/delete a number
+ persistDelKnownDev(getDevTwoAddr());
+ ASSERT_FALSE(persistGetDevNumber(getDevTwoAddr(), PERSIST_NUM_TYPE_SM_RANDOM, &num));
+ ASSERT_TRUE(persistDelDevNumbers(getDevTwoAddr()));
+ ASSERT_TRUE(persistAddDevNumber(getDevTwoAddr(), PERSIST_NUM_TYPE_SM_RANDOM, randNumTwo));
+}
+
+} // namespace
diff --git a/tests/sm_unittest.cc b/tests/sm_unittest.cc
index 339153b..a32168c 100644
--- a/tests/sm_unittest.cc
+++ b/tests/sm_unittest.cc
@@ -124,8 +124,3 @@
}
} // namespace
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/tests/unittest.cc b/tests/unittest.cc
new file mode 100644
index 0000000..11ff69a
--- /dev/null
+++ b/tests/unittest.cc
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <gtest/gtest.h>
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}