Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/bsim.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ jobs:
run: |
uv pip install \
-r pouch/requirements.txt \
-r pouch-gateway/requirements.txt \
-r zephyr/scripts/requirements-base.txt \
-r zephyr/scripts/requirements-build-test.txt \
-r zephyr/scripts/requirements-run-test.txt \
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ jobs:
- name: Install pip packages
run: |
uv pip install \
-r pouch-gateway/requirements.txt \
-r zephyr/scripts/requirements-base.txt

uv pip install \
Expand Down
16 changes: 16 additions & 0 deletions include/pouch_gateway/bt/info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2025 Golioth, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

struct bt_conn;

/**
* Start reading info characteristic for the given Bluetooth connection.
*
* @param conn The Bluetooth connection.
*/
void pouch_gateway_info_read_start(struct bt_conn *conn);
48 changes: 48 additions & 0 deletions include/pouch_gateway/info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2025 Golioth, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

struct pouch_gateway_info_context;

/**
* @brief Start info read operation.
*
* @return Pointer to the info context, or NULL on failure.
*/
struct pouch_gateway_info_context *pouch_gateway_info_start(void);
/**
* @brief Push data to the info context.
*
* @param context The info context.
* @param data The data to push.
* @param len The length of the data.
* @return 0 on success, negative on error.
*/
int pouch_gateway_info_push(struct pouch_gateway_info_context *context,
const void *data,
size_t len);
/**
* @brief Abort the info read operation.
*
* @param context The info context.
*/
void pouch_gateway_info_abort(struct pouch_gateway_info_context *context);
/**
* @brief Finish the info read operation.
*
* @param context The info context.
* @param[out] server_cert_provisioned Set to true if server cert is provisioned.
* @param[out] device_cert_provisioned Set to true if device cert is provisioned.
* @return 0 on success, negative on error.
*/
int pouch_gateway_info_finish(struct pouch_gateway_info_context *context,
bool *server_cert_provisioned,
bool *device_cert_provisioned);
3 changes: 3 additions & 0 deletions include/pouch_gateway/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ struct pouch_gateway_node_info
void *server_cert_scratch;
struct pouch_gatt_packetizer *packetizer;
struct pouch_gateway_uplink *uplink;
struct pouch_gateway_info_context *info_ctx;
struct pouch_gateway_device_cert_context *device_cert_ctx;
struct pouch_gateway_server_cert_context *server_cert_ctx;
bool server_cert_provisioned;
bool device_cert_provisioned;
};

/**
Expand Down
16 changes: 16 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ zephyr_library()
zephyr_library_sources(bt/cert.c)
zephyr_library_sources(bt/connect.c)
zephyr_library_sources(bt/downlink.c)
zephyr_library_sources(bt/info.c)
zephyr_library_sources(bt/scan.c)
zephyr_library_sources(bt/uplink.c)
zephyr_library_sources(block.c)
zephyr_library_sources(cert.c)
zephyr_library_sources(downlink.c)
zephyr_library_sources(info.c)
zephyr_library_sources(info_decode.c)
zephyr_library_sources(uplink.c)

zephyr_library_link_libraries(mbedTLS)
Expand All @@ -23,3 +26,16 @@ endif()
generate_inc_file_for_target(${lib_name}
${cert_name}
${ZEPHYR_BINARY_DIR}/include/generated/pouch_gateway_server.pem.inc)

add_custom_command(OUTPUT info_decode.c
COMMAND zcbor code
-c ${ZEPHYR_POUCH_MODULE_DIR}/src/transport/gatt/info.cddl
-s
-t pouch_gatt_info
-d --include-prefix cddl/
--output-c ${CMAKE_CURRENT_BINARY_DIR}/info_decode.c
--output-h ${CMAKE_CURRENT_BINARY_DIR}/include/cddl/info_decode.h
BYPRODUCTS include/cddl/info_decode.h include/cddl/info_decode_types.h
DEPENDS ${ZEPHYR_POUCH_MODULE_DIR}/src/transport/gatt/info.cddl)

zephyr_library_include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
96 changes: 12 additions & 84 deletions lib/bt/cert.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,72 +51,6 @@ static void server_cert_cleanup(struct bt_conn *conn)
}
}

static uint8_t server_cert_read_cb(struct bt_conn *conn,
uint8_t err,
struct bt_gatt_read_params *params,
const void *data,
uint16_t length)
{
if (err)
{
LOG_ERR("Failed to read BLE GATT %s (err %d)", "server cert", err);
return BT_GATT_ITER_STOP;
}

if (length == 0)
{
gateway_server_cert_write_start(conn);
return BT_GATT_ITER_STOP;
}

bool is_first = false;
bool is_last = false;
const void *payload = NULL;
ssize_t payload_len = pouch_gatt_packetizer_decode(data, length, &payload, &is_first, &is_last);
if (payload_len < 0)
{
LOG_ERR("Failed to decode BLE GATT %s (err %d)", "server cert", (int) payload_len);
server_cert_cleanup(conn);
pouch_gateway_bt_finished(conn);
return BT_GATT_ITER_STOP;
}

if (data)
{
LOG_HEXDUMP_DBG(data, length, "[READ] BLE GATT server cert");
}

if (is_last)
{
uint8_t serial[CERT_SERIAL_MAXLEN];
size_t serial_len = sizeof(serial);

pouch_gateway_server_cert_get_serial(serial, &serial_len);

if (payload_len > 0 && payload_len == serial_len
&& memcmp(serial, payload, payload_len) == 0)
{
LOG_DBG("server cert match");
gateway_device_cert_read_start(conn);
}
else
{
LOG_DBG("server cert mismatch");
gateway_server_cert_write_start(conn);
}

return BT_GATT_ITER_STOP;
}

err = bt_gatt_read(conn, params);
if (err)
{
LOG_ERR("BT (re)read request failed: %d", err);
return BT_GATT_ITER_STOP;
}

return BT_GATT_ITER_STOP;
}

static void device_cert_cleanup(struct bt_conn *conn)
{
Expand Down Expand Up @@ -262,6 +196,7 @@ static void write_response_cb(struct bt_conn *conn,
{
// There was certificate update in the meantime, so send it once again.
LOG_INF("Noticed certificate update, sending once again");
node->server_cert_provisioned = false;
gateway_server_cert_write_start(conn);
}
}
Expand Down Expand Up @@ -301,6 +236,12 @@ static void gateway_server_cert_write_start(struct bt_conn *conn)
{
struct pouch_gateway_node_info *node = pouch_gateway_get_node_info(conn);

if (node->server_cert_provisioned)
{
gateway_device_cert_read_start(conn);
return;
}

if (0 == node->attr_handles[POUCH_GATEWAY_GATT_ATTR_SERVER_CERT].value)
{
LOG_ERR("%s characteristic undiscovered", "server cert");
Expand Down Expand Up @@ -339,28 +280,15 @@ static void gateway_server_cert_write_start(struct bt_conn *conn)
write_server_cert_characteristic(conn);
}

static void gateway_server_cert_serial_read_start(struct bt_conn *conn)
static void gateway_device_cert_read_start(struct bt_conn *conn)
{
struct pouch_gateway_node_info *node = pouch_gateway_get_node_info(conn);

struct bt_gatt_read_params *read_params = &node->read_params;
memset(read_params, 0, sizeof(*read_params));

read_params->func = server_cert_read_cb;
read_params->handle_count = 1;
read_params->single.handle = node->attr_handles[POUCH_GATEWAY_GATT_ATTR_SERVER_CERT].value;
int err = bt_gatt_read(conn, read_params);
if (err)
if (node->device_cert_provisioned)
{
LOG_ERR("BT read request failed: %d", err);
server_cert_cleanup(conn);
pouch_gateway_bt_finished(conn);
pouch_gateway_uplink_start(conn);
return;
}
}

static void gateway_device_cert_read_start(struct bt_conn *conn)
{
struct pouch_gateway_node_info *node = pouch_gateway_get_node_info(conn);

struct bt_gatt_read_params *read_params = &node->read_params;
memset(read_params, 0, sizeof(*read_params));
Expand Down Expand Up @@ -388,5 +316,5 @@ static void gateway_device_cert_read_start(struct bt_conn *conn)

void pouch_gateway_cert_exchange_start(struct bt_conn *conn)
{
gateway_server_cert_serial_read_start(conn);
gateway_server_cert_write_start(conn);
}
4 changes: 2 additions & 2 deletions lib/bt/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

#include <pouch_gateway/types.h>
#include <pouch_gateway/bt/connect.h>
#include <pouch_gateway/bt/cert.h>
#include <pouch_gateway/bt/downlink.h>
#include <pouch_gateway/bt/info.h>
#include <pouch_gateway/bt/scan.h>
#include <pouch_gateway/bt/uplink.h>

Expand Down Expand Up @@ -79,7 +79,7 @@ static uint8_t discover_descriptors(struct bt_conn *conn,
if (node->attr_handles[POUCH_GATEWAY_GATT_ATTR_SERVER_CERT].value
&& node->attr_handles[POUCH_GATEWAY_GATT_ATTR_DEVICE_CERT].value)
{
pouch_gateway_cert_exchange_start(conn);
pouch_gateway_info_read_start(conn);
}
else
{
Expand Down
Loading