summaryrefslogtreecommitdiff
path: root/src/libs/mynewt-nimble/nimble/host/store
diff options
context:
space:
mode:
authorJF <jf@codingfield.com>2020-04-26 10:25:59 +0200
committerJF <jf@codingfield.com>2020-04-26 10:25:59 +0200
commitbdc10744fb338ae197692713a0b48a7ccc36f566 (patch)
treeaf7a8f2f16ddd2e5483758effec15c7683f6c453 /src/libs/mynewt-nimble/nimble/host/store
parent032fad094c6411ad3ff4321ad61ceed95d7dc4ff (diff)
Add Nimble in libs directory
Diffstat (limited to 'src/libs/mynewt-nimble/nimble/host/store')
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/config/include/store/config/ble_store_config.h39
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/config/pkg.yml38
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c533
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config_conf.c231
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config_priv.h59
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/config/syscfg.yml27
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h39
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/ram/pkg.yml37
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c497
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml23
10 files changed, 1523 insertions, 0 deletions
diff --git a/src/libs/mynewt-nimble/nimble/host/store/config/include/store/config/ble_store_config.h b/src/libs/mynewt-nimble/nimble/host/store/config/include/store/config/ble_store_config.h
new file mode 100644
index 00000000..1b3f8e6c
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/config/include/store/config/ble_store_config.h
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef H_BLE_STORE_CONFIG_
+#define H_BLE_STORE_CONFIG_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+union ble_store_key;
+union ble_store_value;
+
+int ble_store_config_read(int obj_type, const union ble_store_key *key,
+ union ble_store_value *value);
+int ble_store_config_write(int obj_type, const union ble_store_value *val);
+int ble_store_config_delete(int obj_type, const union ble_store_key *key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/store/config/pkg.yml b/src/libs/mynewt-nimble/nimble/host/store/config/pkg.yml
new file mode 100644
index 00000000..db80d1df
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/config/pkg.yml
@@ -0,0 +1,38 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+
+pkg.name: nimble/host/store/config
+pkg.description: sys/config-based persistence layer for the NimBLE host.
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+ - nimble
+ - persistence
+
+pkg.deps:
+ - "@apache-mynewt-core/encoding/base64"
+ - nimble/host
+
+pkg.deps.BLE_STORE_CONFIG_PERSIST:
+ - "@apache-mynewt-core/sys/config"
+
+pkg.init:
+ ble_store_config_init: 'MYNEWT_VAL(BLE_STORE_SYSINIT_STAGE)'
diff --git a/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c
new file mode 100644
index 00000000..ce60d1fb
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c
@@ -0,0 +1,533 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include <inttypes.h>
+#include <string.h>
+
+#include "sysinit/sysinit.h"
+#include "syscfg/syscfg.h"
+#include "host/ble_hs.h"
+#include "config/config.h"
+#include "base64/base64.h"
+#include "store/config/ble_store_config.h"
+#include "ble_store_config_priv.h"
+
+struct ble_store_value_sec
+ ble_store_config_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
+int ble_store_config_num_our_secs;
+
+struct ble_store_value_sec
+ ble_store_config_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
+int ble_store_config_num_peer_secs;
+
+struct ble_store_value_cccd
+ ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
+int ble_store_config_num_cccds;
+
+/*****************************************************************************
+ * $sec *
+ *****************************************************************************/
+
+static void
+ble_store_config_print_value_sec(const struct ble_store_value_sec *sec)
+{
+ if (sec->ltk_present) {
+ BLE_HS_LOG(DEBUG, "ediv=%u rand=%llu authenticated=%d ltk=",
+ sec->ediv, sec->rand_num, sec->authenticated);
+ ble_hs_log_flat_buf(sec->ltk, 16);
+ BLE_HS_LOG(DEBUG, " ");
+ }
+ if (sec->irk_present) {
+ BLE_HS_LOG(DEBUG, "irk=");
+ ble_hs_log_flat_buf(sec->irk, 16);
+ BLE_HS_LOG(DEBUG, " ");
+ }
+ if (sec->csrk_present) {
+ BLE_HS_LOG(DEBUG, "csrk=");
+ ble_hs_log_flat_buf(sec->csrk, 16);
+ BLE_HS_LOG(DEBUG, " ");
+ }
+
+ BLE_HS_LOG(DEBUG, "\n");
+}
+
+static void
+ble_store_config_print_key_sec(const struct ble_store_key_sec *key_sec)
+{
+ if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) {
+ BLE_HS_LOG(DEBUG, "peer_addr_type=%d peer_addr=",
+ key_sec->peer_addr.type);
+ ble_hs_log_flat_buf(key_sec->peer_addr.val, 6);
+ BLE_HS_LOG(DEBUG, " ");
+ }
+ if (key_sec->ediv_rand_present) {
+ BLE_HS_LOG(DEBUG, "ediv=0x%02x rand=0x%llx ",
+ key_sec->ediv, key_sec->rand_num);
+ }
+}
+
+static int
+ble_store_config_find_sec(const struct ble_store_key_sec *key_sec,
+ const struct ble_store_value_sec *value_secs,
+ int num_value_secs)
+{
+ const struct ble_store_value_sec *cur;
+ int skipped;
+ int i;
+
+ skipped = 0;
+
+ for (i = 0; i < num_value_secs; i++) {
+ cur = value_secs + i;
+
+ if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) {
+ if (ble_addr_cmp(&cur->peer_addr, &key_sec->peer_addr)) {
+ continue;
+ }
+ }
+
+ if (key_sec->ediv_rand_present) {
+ if (cur->ediv != key_sec->ediv) {
+ continue;
+ }
+
+ if (cur->rand_num != key_sec->rand_num) {
+ continue;
+ }
+ }
+
+ if (key_sec->idx > skipped) {
+ skipped++;
+ continue;
+ }
+
+ return i;
+ }
+
+ return -1;
+}
+
+static int
+ble_store_config_read_our_sec(const struct ble_store_key_sec *key_sec,
+ struct ble_store_value_sec *value_sec)
+{
+ int idx;
+
+ idx = ble_store_config_find_sec(key_sec, ble_store_config_our_secs,
+ ble_store_config_num_our_secs);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ *value_sec = ble_store_config_our_secs[idx];
+ return 0;
+}
+
+
+static int
+ble_store_config_write_our_sec(const struct ble_store_value_sec *value_sec)
+{
+ struct ble_store_key_sec key_sec;
+ int idx;
+ int rc;
+
+ BLE_HS_LOG(DEBUG, "persisting our sec; ");
+ ble_store_config_print_value_sec(value_sec);
+
+ ble_store_key_from_value_sec(&key_sec, value_sec);
+ idx = ble_store_config_find_sec(&key_sec, ble_store_config_our_secs,
+ ble_store_config_num_our_secs);
+ if (idx == -1) {
+ if (ble_store_config_num_our_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
+ BLE_HS_LOG(DEBUG, "error persisting our sec; too many entries "
+ "(%d)\n", ble_store_config_num_our_secs);
+ return BLE_HS_ESTORE_CAP;
+ }
+
+ idx = ble_store_config_num_our_secs;
+ ble_store_config_num_our_secs++;
+ }
+
+ ble_store_config_our_secs[idx] = *value_sec;
+
+ rc = ble_store_config_persist_our_secs();
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_config_delete_obj(void *values, int value_size, int idx,
+ int *num_values)
+{
+ uint8_t *dst;
+ uint8_t *src;
+ int move_count;
+
+ (*num_values)--;
+ if (idx < *num_values) {
+ dst = values;
+ dst += idx * value_size;
+ src = dst + value_size;
+
+ move_count = *num_values - idx;
+ memmove(dst, src, move_count * value_size);
+ }
+
+ return 0;
+}
+
+static int
+ble_store_config_delete_sec(const struct ble_store_key_sec *key_sec,
+ struct ble_store_value_sec *value_secs,
+ int *num_value_secs)
+{
+ int idx;
+ int rc;
+
+ idx = ble_store_config_find_sec(key_sec, value_secs, *num_value_secs);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ rc = ble_store_config_delete_obj(value_secs, sizeof *value_secs, idx,
+ num_value_secs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_config_delete_our_sec(const struct ble_store_key_sec *key_sec)
+{
+ int rc;
+
+ rc = ble_store_config_delete_sec(key_sec, ble_store_config_our_secs,
+ &ble_store_config_num_our_secs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_store_config_persist_our_secs();
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_config_delete_peer_sec(const struct ble_store_key_sec *key_sec)
+{
+ int rc;
+
+ rc = ble_store_config_delete_sec(key_sec, ble_store_config_peer_secs,
+ &ble_store_config_num_peer_secs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_store_config_persist_peer_secs();
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_config_read_peer_sec(const struct ble_store_key_sec *key_sec,
+ struct ble_store_value_sec *value_sec)
+{
+ int idx;
+
+ idx = ble_store_config_find_sec(key_sec, ble_store_config_peer_secs,
+ ble_store_config_num_peer_secs);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ *value_sec = ble_store_config_peer_secs[idx];
+ return 0;
+}
+
+static int
+ble_store_config_write_peer_sec(const struct ble_store_value_sec *value_sec)
+{
+ struct ble_store_key_sec key_sec;
+ int idx;
+ int rc;
+
+ BLE_HS_LOG(DEBUG, "persisting peer sec; ");
+ ble_store_config_print_value_sec(value_sec);
+
+ ble_store_key_from_value_sec(&key_sec, value_sec);
+ idx = ble_store_config_find_sec(&key_sec, ble_store_config_peer_secs,
+ ble_store_config_num_peer_secs);
+ if (idx == -1) {
+ if (ble_store_config_num_peer_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
+ BLE_HS_LOG(DEBUG, "error persisting peer sec; too many entries "
+ "(%d)\n", ble_store_config_num_peer_secs);
+ return BLE_HS_ESTORE_CAP;
+ }
+
+ idx = ble_store_config_num_peer_secs;
+ ble_store_config_num_peer_secs++;
+ }
+
+ ble_store_config_peer_secs[idx] = *value_sec;
+
+ rc = ble_store_config_persist_peer_secs();
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * $cccd *
+ *****************************************************************************/
+
+static int
+ble_store_config_find_cccd(const struct ble_store_key_cccd *key)
+{
+ struct ble_store_value_cccd *cccd;
+ int skipped;
+ int i;
+
+ skipped = 0;
+ for (i = 0; i < ble_store_config_num_cccds; i++) {
+ cccd = ble_store_config_cccds + i;
+
+ if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) {
+ if (ble_addr_cmp(&cccd->peer_addr, &key->peer_addr)) {
+ continue;
+ }
+ }
+
+ if (key->chr_val_handle != 0) {
+ if (cccd->chr_val_handle != key->chr_val_handle) {
+ continue;
+ }
+ }
+
+ if (key->idx > skipped) {
+ skipped++;
+ continue;
+ }
+
+ return i;
+ }
+
+ return -1;
+}
+
+static int
+ble_store_config_delete_cccd(const struct ble_store_key_cccd *key_cccd)
+{
+ int idx;
+ int rc;
+
+ idx = ble_store_config_find_cccd(key_cccd);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ rc = ble_store_config_delete_obj(ble_store_config_cccds,
+ sizeof *ble_store_config_cccds,
+ idx,
+ &ble_store_config_num_cccds);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_store_config_persist_cccds();
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_config_read_cccd(const struct ble_store_key_cccd *key_cccd,
+ struct ble_store_value_cccd *value_cccd)
+{
+ int idx;
+
+ idx = ble_store_config_find_cccd(key_cccd);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ *value_cccd = ble_store_config_cccds[idx];
+ return 0;
+}
+
+static int
+ble_store_config_write_cccd(const struct ble_store_value_cccd *value_cccd)
+{
+ struct ble_store_key_cccd key_cccd;
+ int idx;
+ int rc;
+
+ ble_store_key_from_value_cccd(&key_cccd, value_cccd);
+ idx = ble_store_config_find_cccd(&key_cccd);
+ if (idx == -1) {
+ if (ble_store_config_num_cccds >= MYNEWT_VAL(BLE_STORE_MAX_CCCDS)) {
+ BLE_HS_LOG(DEBUG, "error persisting cccd; too many entries (%d)\n",
+ ble_store_config_num_cccds);
+ return BLE_HS_ESTORE_CAP;
+ }
+
+ idx = ble_store_config_num_cccds;
+ ble_store_config_num_cccds++;
+ }
+
+ ble_store_config_cccds[idx] = *value_cccd;
+
+ rc = ble_store_config_persist_cccds();
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * $api *
+ *****************************************************************************/
+
+/**
+ * Searches the database for an object matching the specified criteria.
+ *
+ * @return 0 if a key was found; else BLE_HS_ENOENT.
+ */
+int
+ble_store_config_read(int obj_type, const union ble_store_key *key,
+ union ble_store_value *value)
+{
+ int rc;
+
+ switch (obj_type) {
+ case BLE_STORE_OBJ_TYPE_PEER_SEC:
+ /* An encryption procedure (bonding) is being attempted. The nimble
+ * stack is asking us to look in our key database for a long-term key
+ * corresponding to the specified ediv and random number.
+ *
+ * Perform a key lookup and populate the context object with the
+ * result. The nimble stack will use this key if this function returns
+ * success.
+ */
+ BLE_HS_LOG(DEBUG, "looking up peer sec; ");
+ ble_store_config_print_key_sec(&key->sec);
+ BLE_HS_LOG(DEBUG, "\n");
+ rc = ble_store_config_read_peer_sec(&key->sec, &value->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_OUR_SEC:
+ BLE_HS_LOG(DEBUG, "looking up our sec; ");
+ ble_store_config_print_key_sec(&key->sec);
+ BLE_HS_LOG(DEBUG, "\n");
+ rc = ble_store_config_read_our_sec(&key->sec, &value->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_CCCD:
+ rc = ble_store_config_read_cccd(&key->cccd, &value->cccd);
+ return rc;
+
+ default:
+ return BLE_HS_ENOTSUP;
+ }
+}
+
+/**
+ * Adds the specified object to the database.
+ *
+ * @return 0 on success;
+ * BLE_HS_ESTORE_CAP if the database is full.
+ */
+int
+ble_store_config_write(int obj_type, const union ble_store_value *val)
+{
+ int rc;
+
+ switch (obj_type) {
+ case BLE_STORE_OBJ_TYPE_PEER_SEC:
+ rc = ble_store_config_write_peer_sec(&val->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_OUR_SEC:
+ rc = ble_store_config_write_our_sec(&val->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_CCCD:
+ rc = ble_store_config_write_cccd(&val->cccd);
+ return rc;
+
+ default:
+ return BLE_HS_ENOTSUP;
+ }
+}
+
+int
+ble_store_config_delete(int obj_type, const union ble_store_key *key)
+{
+ int rc;
+
+ switch (obj_type) {
+ case BLE_STORE_OBJ_TYPE_PEER_SEC:
+ rc = ble_store_config_delete_peer_sec(&key->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_OUR_SEC:
+ rc = ble_store_config_delete_our_sec(&key->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_CCCD:
+ rc = ble_store_config_delete_cccd(&key->cccd);
+ return rc;
+
+ default:
+ return BLE_HS_ENOTSUP;
+ }
+}
+
+void
+ble_store_config_init(void)
+{
+ /* Ensure this function only gets called by sysinit. */
+ SYSINIT_ASSERT_ACTIVE();
+
+ ble_hs_cfg.store_read_cb = ble_store_config_read;
+ ble_hs_cfg.store_write_cb = ble_store_config_write;
+ ble_hs_cfg.store_delete_cb = ble_store_config_delete;
+
+ /* Re-initialize BSS values in case of unit tests. */
+ ble_store_config_num_our_secs = 0;
+ ble_store_config_num_peer_secs = 0;
+ ble_store_config_num_cccds = 0;
+
+ ble_store_config_conf_init();
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config_conf.c b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config_conf.c
new file mode 100644
index 00000000..e74127ae
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config_conf.c
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST)
+
+#include <inttypes.h>
+#include <string.h>
+
+#include "sysinit/sysinit.h"
+#include "host/ble_hs.h"
+#include "config/config.h"
+#include "base64/base64.h"
+#include "store/config/ble_store_config.h"
+#include "ble_store_config_priv.h"
+
+static int
+ble_store_config_conf_set(int argc, char **argv, char *val);
+static int
+ble_store_config_conf_export(void (*func)(char *name, char *val),
+ enum conf_export_tgt tgt);
+
+static struct conf_handler ble_store_config_conf_handler = {
+ .ch_name = "ble_hs",
+ .ch_get = NULL,
+ .ch_set = ble_store_config_conf_set,
+ .ch_commit = NULL,
+ .ch_export = ble_store_config_conf_export
+};
+
+#define BLE_STORE_CONFIG_SEC_ENCODE_SZ \
+ BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_sec))
+
+#define BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ \
+ (MYNEWT_VAL(BLE_STORE_MAX_BONDS) * BLE_STORE_CONFIG_SEC_ENCODE_SZ + 1)
+
+#define BLE_STORE_CONFIG_CCCD_ENCODE_SZ \
+ BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_cccd))
+
+#define BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ \
+ (MYNEWT_VAL(BLE_STORE_MAX_CCCDS) * BLE_STORE_CONFIG_CCCD_ENCODE_SZ + 1)
+
+static void
+ble_store_config_serialize_arr(const void *arr, int obj_sz, int num_objs,
+ char *out_buf, int buf_sz)
+{
+ int arr_size;
+
+ arr_size = obj_sz * num_objs;
+ assert(arr_size <= buf_sz);
+
+ base64_encode(arr, arr_size, out_buf, 1);
+}
+
+static int
+ble_store_config_deserialize_arr(const char *enc,
+ void *out_arr,
+ int obj_sz,
+ int *out_num_objs)
+{
+ int len;
+
+ len = base64_decode(enc, out_arr);
+ if (len < 0) {
+ return OS_EINVAL;
+ }
+
+ *out_num_objs = len / obj_sz;
+ return 0;
+}
+
+static int
+ble_store_config_conf_set(int argc, char **argv, char *val)
+{
+ int rc;
+
+ if (argc == 1) {
+ if (strcmp(argv[0], "our_sec") == 0) {
+ rc = ble_store_config_deserialize_arr(
+ val,
+ ble_store_config_our_secs,
+ sizeof *ble_store_config_our_secs,
+ &ble_store_config_num_our_secs);
+ return rc;
+ } else if (strcmp(argv[0], "peer_sec") == 0) {
+ rc = ble_store_config_deserialize_arr(
+ val,
+ ble_store_config_peer_secs,
+ sizeof *ble_store_config_peer_secs,
+ &ble_store_config_num_peer_secs);
+ return rc;
+ } else if (strcmp(argv[0], "cccd") == 0) {
+ rc = ble_store_config_deserialize_arr(
+ val,
+ ble_store_config_cccds,
+ sizeof *ble_store_config_cccds,
+ &ble_store_config_num_cccds);
+ return rc;
+ }
+ }
+ return OS_ENOENT;
+}
+
+static int
+ble_store_config_conf_export(void (*func)(char *name, char *val),
+ enum conf_export_tgt tgt)
+{
+ union {
+ char sec[BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ];
+ char cccd[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ];
+ } buf;
+
+ ble_store_config_serialize_arr(ble_store_config_our_secs,
+ sizeof *ble_store_config_our_secs,
+ ble_store_config_num_our_secs,
+ buf.sec,
+ sizeof buf.sec);
+ func("ble_hs/our_sec", buf.sec);
+
+ ble_store_config_serialize_arr(ble_store_config_peer_secs,
+ sizeof *ble_store_config_peer_secs,
+ ble_store_config_num_peer_secs,
+ buf.sec,
+ sizeof buf.sec);
+ func("ble_hs/peer_sec", buf.sec);
+
+ ble_store_config_serialize_arr(ble_store_config_cccds,
+ sizeof *ble_store_config_cccds,
+ ble_store_config_num_cccds,
+ buf.cccd,
+ sizeof buf.cccd);
+ func("ble_hs/cccd", buf.cccd);
+
+ return 0;
+}
+
+static int
+ble_store_config_persist_sec_set(const char *setting_name,
+ const struct ble_store_value_sec *secs,
+ int num_secs)
+{
+ char buf[BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ];
+ int rc;
+
+ ble_store_config_serialize_arr(secs, sizeof *secs, num_secs,
+ buf, sizeof buf);
+ rc = conf_save_one(setting_name, buf);
+ if (rc != 0) {
+ return BLE_HS_ESTORE_FAIL;
+ }
+
+ return 0;
+}
+
+int
+ble_store_config_persist_our_secs(void)
+{
+ int rc;
+
+ rc = ble_store_config_persist_sec_set("ble_hs/our_sec",
+ ble_store_config_our_secs,
+ ble_store_config_num_our_secs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+ble_store_config_persist_peer_secs(void)
+{
+ int rc;
+
+ rc = ble_store_config_persist_sec_set("ble_hs/peer_sec",
+ ble_store_config_peer_secs,
+ ble_store_config_num_peer_secs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+ble_store_config_persist_cccds(void)
+{
+ char buf[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ];
+ int rc;
+
+ ble_store_config_serialize_arr(ble_store_config_cccds,
+ sizeof *ble_store_config_cccds,
+ ble_store_config_num_cccds,
+ buf,
+ sizeof buf);
+ rc = conf_save_one("ble_hs/cccd", buf);
+ if (rc != 0) {
+ return BLE_HS_ESTORE_FAIL;
+ }
+
+ return 0;
+}
+
+void
+ble_store_config_conf_init(void)
+{
+ int rc;
+
+ rc = conf_register(&ble_store_config_conf_handler);
+ SYSINIT_PANIC_ASSERT_MSG(rc == 0,
+ "Failed to register ble_store_config conf");
+}
+
+#endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */
diff --git a/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config_priv.h b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config_priv.h
new file mode 100644
index 00000000..bae90e97
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config_priv.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef H_BLE_STORE_CONFIG_PRIV_
+#define H_BLE_STORE_CONFIG_PRIV_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct ble_store_value_sec
+ ble_store_config_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
+extern int ble_store_config_num_our_secs;
+
+extern struct ble_store_value_sec
+ ble_store_config_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
+extern int ble_store_config_num_peer_secs;
+
+extern struct ble_store_value_cccd
+ ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
+extern int ble_store_config_num_cccds;
+
+#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST)
+
+int ble_store_config_persist_our_secs(void);
+int ble_store_config_persist_peer_secs(void);
+int ble_store_config_persist_cccds(void);
+void ble_store_config_conf_init(void);
+
+#else
+
+static inline int ble_store_config_persist_our_secs(void) { return 0; }
+static inline int ble_store_config_persist_peer_secs(void) { return 0; }
+static inline int ble_store_config_persist_cccds(void) { return 0; }
+static inline void ble_store_config_conf_init(void) { }
+
+#endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/store/config/syscfg.yml b/src/libs/mynewt-nimble/nimble/host/store/config/syscfg.yml
new file mode 100644
index 00000000..ff0689c6
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/config/syscfg.yml
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+
+syscfg.defs:
+ BLE_STORE_CONFIG_PERSIST:
+ description: >
+ Whether to save data to sys/config, or just keep it in RAM.
+ value: 1
+ BLE_STORE_SYSINIT_STAGE:
+ description: >
+ Sysinit stage for BLE host store.
+ value: 500
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h b/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h
new file mode 100644
index 00000000..842fb5f3
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef H_BLE_STORE_RAM_
+#define H_BLE_STORE_RAM_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+union ble_store_key;
+union ble_store_value;
+
+int ble_store_ram_read(int obj_type, const union ble_store_key *key,
+ union ble_store_value *value);
+int ble_store_ram_write(int obj_type, const union ble_store_value *val);
+int ble_store_ram_delete(int obj_type, const union ble_store_key *key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/pkg.yml b/src/libs/mynewt-nimble/nimble/host/store/ram/pkg.yml
new file mode 100644
index 00000000..68765fdd
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/pkg.yml
@@ -0,0 +1,37 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+
+pkg.name: nimble/host/store/ram
+pkg.description: >
+ DEPRECATED; for a RAM-only BLE store, use store/config and set
+ BLE_STORE_CONFIG_PERSIST to 0. RAM-based persistence layer for the NimBLE
+ host.
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+ - nimble
+ - persistence
+
+pkg.deps:
+ - nimble/host
+
+pkg.init:
+ ble_store_ram_init: 'MYNEWT_VAL(BLE_STORE_RAM_SYSINIT_STAGE)'
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c b/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c
new file mode 100644
index 00000000..ab5cdb9f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c
@@ -0,0 +1,497 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * This file implements a simple in-RAM key database for BLE host security
+ * material and CCCDs. As this database is only ble_store_ramd in RAM, its
+ * contents are lost when the application terminates.
+ */
+
+#include <inttypes.h>
+#include <string.h>
+
+#include "sysinit/sysinit.h"
+#include "syscfg/syscfg.h"
+#include "host/ble_hs.h"
+#include "store/ram/ble_store_ram.h"
+
+static struct ble_store_value_sec
+ ble_store_ram_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
+static int ble_store_ram_num_our_secs;
+
+static struct ble_store_value_sec
+ ble_store_ram_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
+static int ble_store_ram_num_peer_secs;
+
+static struct ble_store_value_cccd
+ ble_store_ram_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
+static int ble_store_ram_num_cccds;
+
+/*****************************************************************************
+ * $sec *
+ *****************************************************************************/
+
+static void
+ble_store_ram_print_value_sec(const struct ble_store_value_sec *sec)
+{
+ if (sec->ltk_present) {
+ BLE_HS_LOG(DEBUG, "ediv=%u rand=%llu authenticated=%d ltk=",
+ sec->ediv, sec->rand_num, sec->authenticated);
+ ble_hs_log_flat_buf(sec->ltk, 16);
+ BLE_HS_LOG(DEBUG, " ");
+ }
+ if (sec->irk_present) {
+ BLE_HS_LOG(DEBUG, "irk=");
+ ble_hs_log_flat_buf(sec->irk, 16);
+ BLE_HS_LOG(DEBUG, " ");
+ }
+ if (sec->csrk_present) {
+ BLE_HS_LOG(DEBUG, "csrk=");
+ ble_hs_log_flat_buf(sec->csrk, 16);
+ BLE_HS_LOG(DEBUG, " ");
+ }
+
+ BLE_HS_LOG(DEBUG, "\n");
+}
+
+static void
+ble_store_ram_print_key_sec(const struct ble_store_key_sec *key_sec)
+{
+ if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) {
+ BLE_HS_LOG(DEBUG, "peer_addr_type=%d peer_addr=",
+ key_sec->peer_addr.type);
+ ble_hs_log_flat_buf(key_sec->peer_addr.val, 6);
+ BLE_HS_LOG(DEBUG, " ");
+ }
+ if (key_sec->ediv_rand_present) {
+ BLE_HS_LOG(DEBUG, "ediv=0x%02x rand=0x%llx ",
+ key_sec->ediv, key_sec->rand_num);
+ }
+}
+
+static int
+ble_store_ram_find_sec(const struct ble_store_key_sec *key_sec,
+ const struct ble_store_value_sec *value_secs,
+ int num_value_secs)
+{
+ const struct ble_store_value_sec *cur;
+ int skipped;
+ int i;
+
+ skipped = 0;
+
+ for (i = 0; i < num_value_secs; i++) {
+ cur = value_secs + i;
+
+ if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) {
+ if (ble_addr_cmp(&cur->peer_addr, &key_sec->peer_addr)) {
+ continue;
+ }
+ }
+
+ if (key_sec->ediv_rand_present) {
+ if (cur->ediv != key_sec->ediv) {
+ continue;
+ }
+
+ if (cur->rand_num != key_sec->rand_num) {
+ continue;
+ }
+ }
+
+ if (key_sec->idx > skipped) {
+ skipped++;
+ continue;
+ }
+
+ return i;
+ }
+
+ return -1;
+}
+
+static int
+ble_store_ram_read_our_sec(const struct ble_store_key_sec *key_sec,
+ struct ble_store_value_sec *value_sec)
+{
+ int idx;
+
+ idx = ble_store_ram_find_sec(key_sec, ble_store_ram_our_secs,
+ ble_store_ram_num_our_secs);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ *value_sec = ble_store_ram_our_secs[idx];
+ return 0;
+}
+
+static int
+ble_store_ram_write_our_sec(const struct ble_store_value_sec *value_sec)
+{
+ struct ble_store_key_sec key_sec;
+ int idx;
+
+ BLE_HS_LOG(DEBUG, "persisting our sec; ");
+ ble_store_ram_print_value_sec(value_sec);
+
+ ble_store_key_from_value_sec(&key_sec, value_sec);
+ idx = ble_store_ram_find_sec(&key_sec, ble_store_ram_our_secs,
+ ble_store_ram_num_our_secs);
+ if (idx == -1) {
+ if (ble_store_ram_num_our_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
+ BLE_HS_LOG(DEBUG, "error persisting our sec; too many entries "
+ "(%d)\n", ble_store_ram_num_our_secs);
+ return BLE_HS_ESTORE_CAP;
+ }
+
+ idx = ble_store_ram_num_our_secs;
+ ble_store_ram_num_our_secs++;
+ }
+
+ ble_store_ram_our_secs[idx] = *value_sec;
+ return 0;
+}
+
+static int
+ble_store_ram_delete_obj(void *values, int value_size, int idx,
+ int *num_values)
+{
+ uint8_t *dst;
+ uint8_t *src;
+ int move_count;
+
+ (*num_values)--;
+ if (idx < *num_values) {
+ dst = values;
+ dst += idx * value_size;
+ src = dst + value_size;
+
+ move_count = *num_values - idx;
+ memmove(dst, src, move_count);
+ }
+
+ return 0;
+}
+
+static int
+ble_store_ram_delete_sec(const struct ble_store_key_sec *key_sec,
+ struct ble_store_value_sec *value_secs,
+ int *num_value_secs)
+{
+ int idx;
+ int rc;
+
+ idx = ble_store_ram_find_sec(key_sec, value_secs, *num_value_secs);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ rc = ble_store_ram_delete_obj(value_secs, sizeof *value_secs, idx,
+ num_value_secs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_ram_delete_our_sec(const struct ble_store_key_sec *key_sec)
+{
+ int rc;
+
+ rc = ble_store_ram_delete_sec(key_sec, ble_store_ram_our_secs,
+ &ble_store_ram_num_our_secs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_ram_delete_peer_sec(const struct ble_store_key_sec *key_sec)
+{
+ int rc;
+
+ rc = ble_store_ram_delete_sec(key_sec, ble_store_ram_peer_secs,
+ &ble_store_ram_num_peer_secs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_ram_read_peer_sec(const struct ble_store_key_sec *key_sec,
+ struct ble_store_value_sec *value_sec)
+{
+ int idx;
+
+ idx = ble_store_ram_find_sec(key_sec, ble_store_ram_peer_secs,
+ ble_store_ram_num_peer_secs);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ *value_sec = ble_store_ram_peer_secs[idx];
+ return 0;
+}
+
+static int
+ble_store_ram_write_peer_sec(const struct ble_store_value_sec *value_sec)
+{
+ struct ble_store_key_sec key_sec;
+ int idx;
+
+ BLE_HS_LOG(DEBUG, "persisting peer sec; ");
+ ble_store_ram_print_value_sec(value_sec);
+
+ ble_store_key_from_value_sec(&key_sec, value_sec);
+ idx = ble_store_ram_find_sec(&key_sec, ble_store_ram_peer_secs,
+ ble_store_ram_num_peer_secs);
+ if (idx == -1) {
+ if (ble_store_ram_num_peer_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
+ BLE_HS_LOG(DEBUG, "error persisting peer sec; too many entries "
+ "(%d)\n", ble_store_ram_num_peer_secs);
+ return BLE_HS_ESTORE_CAP;
+ }
+
+ idx = ble_store_ram_num_peer_secs;
+ ble_store_ram_num_peer_secs++;
+ }
+
+ ble_store_ram_peer_secs[idx] = *value_sec;
+ return 0;
+}
+
+/*****************************************************************************
+ * $cccd *
+ *****************************************************************************/
+
+static int
+ble_store_ram_find_cccd(const struct ble_store_key_cccd *key)
+{
+ struct ble_store_value_cccd *cccd;
+ int skipped;
+ int i;
+
+ skipped = 0;
+ for (i = 0; i < ble_store_ram_num_cccds; i++) {
+ cccd = ble_store_ram_cccds + i;
+
+ if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) {
+ if (ble_addr_cmp(&cccd->peer_addr, &key->peer_addr)) {
+ continue;
+ }
+ }
+
+ if (key->chr_val_handle != 0) {
+ if (cccd->chr_val_handle != key->chr_val_handle) {
+ continue;
+ }
+ }
+
+ if (key->idx > skipped) {
+ skipped++;
+ continue;
+ }
+
+ return i;
+ }
+
+ return -1;
+}
+
+static int
+ble_store_ram_delete_cccd(const struct ble_store_key_cccd *key_cccd)
+{
+ int idx;
+ int rc;
+
+ idx = ble_store_ram_find_cccd(key_cccd);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ rc = ble_store_ram_delete_obj(ble_store_ram_cccds,
+ sizeof *ble_store_ram_cccds,
+ idx,
+ &ble_store_ram_num_cccds);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_store_ram_read_cccd(const struct ble_store_key_cccd *key_cccd,
+ struct ble_store_value_cccd *value_cccd)
+{
+ int idx;
+
+ idx = ble_store_ram_find_cccd(key_cccd);
+ if (idx == -1) {
+ return BLE_HS_ENOENT;
+ }
+
+ *value_cccd = ble_store_ram_cccds[idx];
+ return 0;
+}
+
+static int
+ble_store_ram_write_cccd(const struct ble_store_value_cccd *value_cccd)
+{
+ struct ble_store_key_cccd key_cccd;
+ int idx;
+
+ ble_store_key_from_value_cccd(&key_cccd, value_cccd);
+ idx = ble_store_ram_find_cccd(&key_cccd);
+ if (idx == -1) {
+ if (ble_store_ram_num_cccds >= MYNEWT_VAL(BLE_STORE_MAX_CCCDS)) {
+ BLE_HS_LOG(DEBUG, "error persisting cccd; too many entries (%d)\n",
+ ble_store_ram_num_cccds);
+ return BLE_HS_ESTORE_CAP;
+ }
+
+ idx = ble_store_ram_num_cccds;
+ ble_store_ram_num_cccds++;
+ }
+
+ ble_store_ram_cccds[idx] = *value_cccd;
+ return 0;
+}
+
+/*****************************************************************************
+ * $api *
+ *****************************************************************************/
+
+/**
+ * Searches the database for an object matching the specified criteria.
+ *
+ * @return 0 if a key was found; else BLE_HS_ENOENT.
+ */
+int
+ble_store_ram_read(int obj_type, const union ble_store_key *key,
+ union ble_store_value *value)
+{
+ int rc;
+
+ switch (obj_type) {
+ case BLE_STORE_OBJ_TYPE_PEER_SEC:
+ /* An encryption procedure (bonding) is being attempted. The nimble
+ * stack is asking us to look in our key database for a long-term key
+ * corresponding to the specified ediv and random number.
+ *
+ * Perform a key lookup and populate the context object with the
+ * result. The nimble stack will use this key if this function returns
+ * success.
+ */
+ BLE_HS_LOG(DEBUG, "looking up peer sec; ");
+ ble_store_ram_print_key_sec(&key->sec);
+ BLE_HS_LOG(DEBUG, "\n");
+ rc = ble_store_ram_read_peer_sec(&key->sec, &value->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_OUR_SEC:
+ BLE_HS_LOG(DEBUG, "looking up our sec; ");
+ ble_store_ram_print_key_sec(&key->sec);
+ BLE_HS_LOG(DEBUG, "\n");
+ rc = ble_store_ram_read_our_sec(&key->sec, &value->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_CCCD:
+ rc = ble_store_ram_read_cccd(&key->cccd, &value->cccd);
+ return rc;
+
+ default:
+ return BLE_HS_ENOTSUP;
+ }
+}
+
+/**
+ * Adds the specified object to the database.
+ *
+ * @return 0 on success; BLE_HS_ESTORE_CAP if the database
+ * is full.
+ */
+int
+ble_store_ram_write(int obj_type, const union ble_store_value *val)
+{
+ int rc;
+
+ switch (obj_type) {
+ case BLE_STORE_OBJ_TYPE_PEER_SEC:
+ rc = ble_store_ram_write_peer_sec(&val->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_OUR_SEC:
+ rc = ble_store_ram_write_our_sec(&val->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_CCCD:
+ rc = ble_store_ram_write_cccd(&val->cccd);
+ return rc;
+
+ default:
+ return BLE_HS_ENOTSUP;
+ }
+}
+
+int
+ble_store_ram_delete(int obj_type, const union ble_store_key *key)
+{
+ int rc;
+
+ switch (obj_type) {
+ case BLE_STORE_OBJ_TYPE_PEER_SEC:
+ rc = ble_store_ram_delete_peer_sec(&key->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_OUR_SEC:
+ rc = ble_store_ram_delete_our_sec(&key->sec);
+ return rc;
+
+ case BLE_STORE_OBJ_TYPE_CCCD:
+ rc = ble_store_ram_delete_cccd(&key->cccd);
+ return rc;
+
+ default:
+ return BLE_HS_ENOTSUP;
+ }
+}
+
+void
+ble_store_ram_init(void)
+{
+ /* Ensure this function only gets called by sysinit. */
+ SYSINIT_ASSERT_ACTIVE();
+
+ ble_hs_cfg.store_read_cb = ble_store_ram_read;
+ ble_hs_cfg.store_write_cb = ble_store_ram_write;
+ ble_hs_cfg.store_delete_cb = ble_store_ram_delete;
+
+ /* Re-initialize BSS values in case of unit tests. */
+ ble_store_ram_num_our_secs = 0;
+ ble_store_ram_num_peer_secs = 0;
+ ble_store_ram_num_cccds = 0;
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml b/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml
new file mode 100644
index 00000000..442211dd
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+syscfg.defs:
+ BLE_STORE_RAM_SYSINIT_STAGE:
+ description: >
+ Sysinit stage for the RAM BLE store.
+ value: 500
+