From 502bb5d9c8b579ea0f7eb426fc4a2c3c091efd09 Mon Sep 17 00:00:00 2001 From: shwetathecodewarrior <121197616+shwetathecodewarrior@users.noreply.github.com> Date: Mon, 19 May 2025 19:59:42 +0000 Subject: [PATCH] Remove Embedded SDK related code --- README.md | 4 - embedded/Makefile | 213 - embedded/README.md | 43 - embedded/build.sh | 97 - embedded/client/source/nearby_fp_client.c | 2016 --------- embedded/client/source/nearby_fp_client.h | 114 - embedded/client/tests/gLinux/audio.cc | 188 - embedded/client/tests/gLinux/battery.cc | 65 - embedded/client/tests/gLinux/ble.cc | 140 - embedded/client/tests/gLinux/bt.cc | 165 - embedded/client/tests/gLinux/fakes.h | 198 - embedded/client/tests/gLinux/os.cc | 82 - embedded/client/tests/gLinux/persistence.cc | 75 - embedded/client/tests/gLinux/se.cc | 262 -- embedded/client/tests/gLinux/trace.cc | 42 - embedded/client/tests/message_stream_test.cc | 363 -- embedded/client/tests/smoke_test.cc | 3698 ----------------- embedded/common/source/mbedtls/gen_secret.c | 108 - embedded/common/source/mbedtls/mbedtls.c | 121 - embedded/common/source/nearby_assert.h | 45 - embedded/common/source/nearby_config.h | 79 - embedded/common/source/nearby_event.h | 252 -- embedded/common/source/nearby_fp_library.c | 833 ---- embedded/common/source/nearby_fp_library.h | 317 -- .../common/source/nearby_message_stream.c | 126 - .../common/source/nearby_message_stream.h | 101 - embedded/common/source/nearby_trace.h | 84 - embedded/common/source/nearby_utils.c | 96 - embedded/common/source/nearby_utils.cc | 14 - embedded/common/source/nearby_utils.h | 45 - embedded/common/target/gLinux/nearby_types.h | 31 - embedded/common/target/nearby.h | 60 - .../common/target/nearby_platform_audio.h | 196 - .../common/target/nearby_platform_battery.h | 56 - embedded/common/target/nearby_platform_ble.h | 108 - embedded/common/target/nearby_platform_bt.h | 121 - embedded/common/target/nearby_platform_os.h | 80 - .../target/nearby_platform_persistence.h | 55 - embedded/common/target/nearby_platform_se.h | 86 - .../common/target/nearby_platform_trace.h | 60 - embedded/release_notes.md | 35 - embedded/target/gLinux/config.mk | 47 - embedded/target/gLinux/rules.mk | 122 - third_party/mbedtls | 1 - third_party/micro-ecc | 1 - 45 files changed, 11045 deletions(-) delete mode 100644 embedded/Makefile delete mode 100644 embedded/README.md delete mode 100755 embedded/build.sh delete mode 100644 embedded/client/source/nearby_fp_client.c delete mode 100644 embedded/client/source/nearby_fp_client.h delete mode 100644 embedded/client/tests/gLinux/audio.cc delete mode 100644 embedded/client/tests/gLinux/battery.cc delete mode 100644 embedded/client/tests/gLinux/ble.cc delete mode 100644 embedded/client/tests/gLinux/bt.cc delete mode 100644 embedded/client/tests/gLinux/fakes.h delete mode 100644 embedded/client/tests/gLinux/os.cc delete mode 100644 embedded/client/tests/gLinux/persistence.cc delete mode 100644 embedded/client/tests/gLinux/se.cc delete mode 100644 embedded/client/tests/gLinux/trace.cc delete mode 100644 embedded/client/tests/message_stream_test.cc delete mode 100644 embedded/client/tests/smoke_test.cc delete mode 100644 embedded/common/source/mbedtls/gen_secret.c delete mode 100644 embedded/common/source/mbedtls/mbedtls.c delete mode 100644 embedded/common/source/nearby_assert.h delete mode 100644 embedded/common/source/nearby_config.h delete mode 100644 embedded/common/source/nearby_event.h delete mode 100644 embedded/common/source/nearby_fp_library.c delete mode 100644 embedded/common/source/nearby_fp_library.h delete mode 100644 embedded/common/source/nearby_message_stream.c delete mode 100644 embedded/common/source/nearby_message_stream.h delete mode 100644 embedded/common/source/nearby_trace.h delete mode 100644 embedded/common/source/nearby_utils.c delete mode 100644 embedded/common/source/nearby_utils.cc delete mode 100644 embedded/common/source/nearby_utils.h delete mode 100644 embedded/common/target/gLinux/nearby_types.h delete mode 100644 embedded/common/target/nearby.h delete mode 100644 embedded/common/target/nearby_platform_audio.h delete mode 100644 embedded/common/target/nearby_platform_battery.h delete mode 100644 embedded/common/target/nearby_platform_ble.h delete mode 100644 embedded/common/target/nearby_platform_bt.h delete mode 100644 embedded/common/target/nearby_platform_os.h delete mode 100644 embedded/common/target/nearby_platform_persistence.h delete mode 100644 embedded/common/target/nearby_platform_se.h delete mode 100644 embedded/common/target/nearby_platform_trace.h delete mode 100644 embedded/release_notes.md delete mode 100644 embedded/target/gLinux/config.mk delete mode 100644 embedded/target/gLinux/rules.mk delete mode 160000 third_party/mbedtls delete mode 160000 third_party/micro-ecc diff --git a/README.md b/README.md index 859c3483..bab47915 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,6 @@ A peer-to-peer networking API that allows apps to easily discover, connect to, a An extension to Nearby Connections that features an extensible identity model for authentication and restricted visibility, resource management for system health, and proximity detection through sensor fusion. -### [Nearby for Embedded Systems](embedded/) - -A lightweight implementation of Fast Pair intended for embedded systems. - ## Contributing We encourage you to contribute to Nearby! Please check out the [Contributing to Nearby guide](CONTRIBUTING.md) for guidelines about how to proceed. diff --git a/embedded/Makefile b/embedded/Makefile deleted file mode 100644 index 4f25308d..00000000 --- a/embedded/Makefile +++ /dev/null @@ -1,213 +0,0 @@ -# Makefile arguments -# -# -# Delete the default suffix rules. -.SUFFIXES: -.SECONDARY: - -GTEST_DIR = ../third_party/gtest/googletest/ -GMOCK_DIR = ../third_party/gtest/googlemock/ -MBEDTLS_DIR = ../third_party/mbedtls/ - - -ARCH ?= host -OUT_DIR_NAME ?= $(ARCH) -OUT_DIR = out/$(OUT_DIR_NAME) -DIST_DIR = dist/$(OUT_DIR_NAME) - -CFLAGS := -Wall -COMMON_INCLUDE_DIRS := -CLIENT_INCLUDES := -# For ARCH variants like gLinux_hw set to gLinux. -ARCH_COMMON_NAME := $(ARCH) -ARCH_COMMON_DIR = common/source/$(ARCH_COMMON_NAME) -CLIENT_DIR = client/source -CLIENT_SRCS := - -NEARBY_LIB_NAME = libnearby.a - -NAME = $(OUT_DIR)/$(NEARBY_LIB_NAME) - -all : $(NAME) - -COMMON_DIR = common/source -COMMON_C_FILES := - -# All output objects for the build system should be added to ALL_OBJS. -ALL_OBJS := -# Extra dependencies of the dist target. -DIST_LIST := - -# Name of the libnearby static library that we distribute. -DIST_NEARBY_LIB_NAME ?= $(DIST_DIR)/$(NEARBY_LIB_NAME) - -# Kokoro on Windows is wonky. We can't shell out to git because we are in -# cygwin, so this is pre-computed by continuous.bat -ifneq ($(FIRMWARE_VERSION_FILENAME),) -FIRMWARE_VERSION := $(shell cat $(FIRMWARE_VERSION_FILENAME)) -else -FIRMWARE_VERSION_FILENAME = $(OUT_DIR)/FIRMWARE_VERSION -PHONY_VERSION_FILENAME = $(OUT_DIR)/PHONY_FIRMWARE_VERSION -FIRMWARE_VERSION := $(shell git -c core.fileMode=false describe --always --dirty --exclude="*") -FIRMWARE_VERSION_FILENAME: $(PHONY_VERSION_FILENAME) - -ifneq ($(KOKORO_RELEASE_BUILD),1) -FIRMWARE_VERSION := $(FIRMWARE_VERSION)ENG -endif - -# Update the phony version on every build. -.PHONY: $(PHONY_VERSION_FILENAME) -$(PHONY_VERSION_FILENAME): - @mkdir -p $(dir $@) ;\ - echo $(FIRMWARE_VERSION) > $@ ;\ - -# Only update this version if necessary (if it's different from the phony). This -# tricks make into not updating dependencies of FIRMWARE_VERSION_FILENAME unless -# the file is updated. .PHONY is not transitive. -$(FIRMWARE_VERSION_FILENAME): $(PHONY_VERSION_FILENAME) - @cmp $@ $< 2>> /dev/null || cp -v $< $@ - -endif - -# Note $(notdir) below converts a path to just the base file name -define compile_c - mkdir -p $(dir $@) - $(CC) -c $(1) -o $@ -D__NEARBY_SHORT_FILE__='"$(notdir $<)"' $< -endef - -# Include all of the target specific variables and rules. -# The $(ARCH).mk files should only depend on the variables listed above. -include target/$(ARCH)/config.mk - -# Set trace verbosity from target specific variable -CFLAGS += -DNEARBY_TRACE_LEVEL=NEARBY_TRACE_LEVEL_$(NEARBY_TRACE_LEVEL) -# if directory doesn't exist, raise an error so we don't fail later with more cryptic warnings -ifeq ($(wildcard common/target/$(ARCH_COMMON_NAME)),) -$(error need to create directory common/target/$(ARCH_COMMON_NAME) ) -endif - -ifdef NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -CFLAGS += -DNEARBY_FP_ENABLE_BATTERY_NOTIFICATION=$(NEARBY_FP_ENABLE_BATTERY_NOTIFICATION) -endif - -ifdef NEARBY_FP_ENABLE_ADDITIONAL_DATA -CFLAGS += -DNEARBY_FP_ENABLE_ADDITIONAL_DATA=$(NEARBY_FP_ENABLE_ADDITIONAL_DATA) -endif - -ifdef NEARBY_FP_MESSAGE_STREAM -CFLAGS += -DNEARBY_FP_MESSAGE_STREAM=$(NEARBY_FP_MESSAGE_STREAM) -endif - -ifdef NEARBY_FP_RETROACTIVE_PAIRING -CFLAGS += -DNEARBY_FP_RETROACTIVE_PAIRING=$(NEARBY_FP_RETROACTIVE_PAIRING) -endif - -ifdef NEARBY_FP_BLE_ONLY -CFLAGS += -DNEARBY_FP_BLE_ONLY=$(NEARBY_FP_BLE_ONLY) -endif - -ifdef NEARBY_FP_PREFER_BLE_BONDING -CFLAGS += -DNEARBY_FP_PREFER_BLE_BONDING=$(NEARBY_FP_PREFER_BLE_BONDING) -endif - -ifdef NEARBY_FP_PREFER_LE_TRANSPORT -CFLAGS += -DNEARBY_FP_PREFER_LE_TRANSPORT=$(NEARBY_FP_PREFER_LE_TRANSPORT) -endif -COMMON_INCLUDE_DIRS += \ - -I. \ - -I$(ARCH_COMMON_DIR) \ - -Icommon/target \ - -Icommon/target/$(ARCH_COMMON_NAME) \ - -I$(COMMON_DIR) -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -COMMON_INCLUDE_DIRS += -I$(MBEDTLS_DIR)/include -endif - -CLIENT_INCLUDES += \ - -I$(CLIENT_DIR) \ - -Iclient/target - -COMMON_C_FILES += \ - $(wildcard $(COMMON_DIR)/*.c) - -CLIENT_SRCS += \ - $(wildcard $(CLIENT_DIR)/*.c) - -CFLAGS += $(COMMON_INCLUDE_DIRS) - -CROSS_COMPILE ?= arm-none-eabi- -CC ?= $(CROSS_COMPILE)gcc -AR ?= $(CROSS_COMPILE)ar -ALL_C_FILES = $(COMMON_C_FILES) -COMMON_OBJS = $(patsubst %.c,$(OUT_DIR)/%.o,$(ALL_C_FILES)) -CLIENT_OBJS = $(patsubst %.c,$(OUT_DIR)/%.o,$(CLIENT_SRCS)) -NEARBY_LIB_OBJS = $(COMMON_OBJS) $(CLIENT_OBJS) - -NEARBY_HEADERS += $(patsubst common/target/%.h,$(DIST_DIR)/%.h,$(wildcard common/target/*.h)) -NEARBY_HEADERS += $(patsubst common/target/$(ARCH_COMMON_NAME)/%.h,$(DIST_DIR)/%.h,$(wildcard common/target/$(ARCH_COMMON_NAME)/*.h)) -NEARBY_HEADERS += $(patsubst client/target/%,$(DIST_DIR)/%,$(wildcard client/target/*.h)) - -NEARBY_DIST_HEADERS := $(NEARBY_HEADERS) - -DIST_LIST += $(NEARBY_DIST_HEADERS) -DIST_LIST += $(DIST_NEARBY_LIB_NAME) - -$(DIST_DIR)/nearby.h: $(FIRMWARE_VERSION_FILENAME) -$(DIST_DIR)/nearby.h: common/target/nearby.h - @mkdir -p $(dir $@) - $(call copy_dist_header) - sed -i -e "s/\(define\s*NEARBY_BUILD_ID\).*/\1 \"$(FIRMWARE_VERSION)\"/" $@ - -define copy_dist_header - @mkdir -p $(dir $@) - @test "$$(head -n 2 $< | grep 'Copyright [0-9]\{4\} Google LLC.')" != "" || \ - (echo ; echo "=====ERROR=====" ; echo "Missing copyright in $<" ; exit 1) - unifdef -t -b -x2 $(UNIFDEF_ARG) -o - $< | cat - >$@ - @# (mkartoz) Should be able to specify $@ as the output directly from - @# unifdef but, if you do that, the file never shows up on kokoro. Piping to - @# cat is a workaround. -endef - -# Do not bypass the whole build process if the dist directory exists -.PHONY: dist -dist : all \ - $(DIST_LIST) - -$(DIST_DIR)/$(NEARBY_LIB_NAME) : $(NAME) - mkdir -p $(dir $@) - cp -uv $< $@ - -$(DIST_DIR)/%.h : common/target/%.h - $(call copy_dist_header) - -$(DIST_DIR)/%.h : common/target/$(ARCH_COMMON_NAME)/%.h - $(call copy_dist_header) - -$(NAME): $(NEARBY_LIB_OBJS) - mkdir -p $(dir $@) - $(AR) rcs $@ $(NEARBY_LIB_OBJS) - -# If the hash has changed then we need to rebuild nearby.o and nearby_client.o -$(filter %/nearby_client.o, $(NEARBY_LIB_OBJS)): $(FIRMWARE_VERSION_FILENAME) -$(filter %/nearby.o, $(NEARBY_LIB_OBJS)): $(FIRMWARE_VERSION_FILENAME) - -$(CLIENT_OBJS) : $(OUT_DIR)/%.o : %.c - $(call compile_c, $(CFLAGS) -Icommon/target $(CLIENT_INCLUDES)) - -$(COMMON_OBJS) : $(OUT_DIR)/%.o: %.c - $(call compile_c,$(CFLAGS)) - -ALL_OBJS += $(NEARBY_LIB_OBJS) $(CLIENT_OBJS) - -DEPFILES = $(ALL_OBJS:.o=.d) - --include $(DEPFILES) - -.PHONY: clean -clean: - rm -f $(NAME) - rm -f $(ALL_OBJS) $(DEPFILES) - rm -f $(FIRMWARE_VERSION_FILENAME) $(PHONY_VERSION_FILENAME) - rm -f $(DIST_LIST) $(TEST_BINARIES) - --include target/$(ARCH)/rules.mk diff --git a/embedded/README.md b/embedded/README.md deleted file mode 100644 index 55c7ec2f..00000000 --- a/embedded/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Nearby embedded SDK library - -This repository contains Nearby SDK library for embedded systems. Nearby SDK -implements the Fast Pair protocol and its future versions per -https://developers.google.com/nearby/fast-pair/spec - - -## Threading model - -Nearby SDK assumes a single-threading model. All calls to the SDK must be on the same thread, or protected with a mutex. That includes: -- client API, for example `nearby_fp_client_SetAdvertisement()` -- ble and other event callbacks -- timers - -## Porting guidelines - -1. Follow the steps at [Fast Pair Help](https://developers.google.com/nearby/fast-pair/help) to - register a Model Id for your device. -1. Review `nearby_config.h` and disable features, if any, that you don't - wish to support. -1. Implement the HAL defined in `nearby_platform_*.h` headers. -1. Set platform specific compile flags in `config.mk` - see - `target/gLinux/config.mk` for inspiration, and add your platform in - `build.sh`, or use your own build system. -1. Compile with `./build.sh ` -1. Start advertising in your application. For example - ``` - nearby_fp_client_Init(NULL); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); - ``` -1. Use [Fast Pair Validator](https://play.google.com/store/apps/details?id=com.google.location.nearby.apps.fastpair.validator) to verify that your device is behaving correctly. - -## Optional modules -The optional modules provide partial implementation of HAL interfaces using common libraries, mbedtls in particular. - -1. *mbedtls* located in `common/source/mbedtls/mbedtls.c` implements `nearby_platform_Sha256Start()`, `nearby_platform_Sha256Update()`, `nearby_platform_Sha256Finish()`, `nearby_platform_Aes128Encrypt()`, `nearby_platform_Aes128Decrypt()`. - -Nearby SDK can be configured to use the MBEDTLS package, commonly available on ARM -implementations, with the config.mk flag `NEARBY_PLATFORM_USE_MBEDTLS`. - -2. *gen_secret* located in `common/source/mbedtls/gen_secret.c` implements `nearby_platform_GenSec256r1Secret()`. - -*gen_secret* generates a shared secret based on a given private key on platforms that don't support hardware SE. *gen_secret* module is enabled `NEARBY_PLATFORM_USE_MBEDTLS` is set and `NEARBY_PLATFORM_HAS_SE` is *not* set. When `NEARBY_PLATFORM_HAS_SE` is set, the platform needs to provide their own `nearby_platform_GenSec256r1Secret()` routine. diff --git a/embedded/build.sh b/embedded/build.sh deleted file mode 100755 index 7c2f68cd..00000000 --- a/embedded/build.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/sh -# Copyright 2022 Google LLC -# -# Licensed 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 -# -# https://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. - -# -# Parameters: -# ${1} architecture (default: gLinux) -# ${2} make target (e.g. "dist") -# (remaining params are also passed to make) -# -# Checks for environment variables: -# NEARBY_MAKEFILE_DEBUG: if set, passes -d argument to make -# many others, not fully documented here yet -# -# e.g. -# ./build.sh gLinux dist DEBUG=1 - -if [ "${1}" == "help" ] ; then - echo "Usage:" - echo " ./build.sh [dist] [args]" - echo "" - echo "Optional arguments:" - echo " DEBUG=1" - echo " -j72 # parallelizes build using 72 cores" - exit -1; -fi - -if [ "${1}" != "" ] ; then - ARCH="${1}" - shift 1 -else - ARCH=gLinux -fi - -CC=arm-none-eabi-gcc -AR=arm-none-eabi-ar - -UNAME_OUT="$(uname -s)" -case "${UNAME_OUT}" in - Linux*) MACHINE=linux;; - Darwin*) MACHINE=mac;; - CYGWIN*) MACHINE=cygwin;; - MINGW*) MACHINE=mingw;; - *) MACHINE=windows;; -esac - -if [ "${ARCH}" = "gLinux" ] ; then - if [ -x /usr/bin/clang ] ; then - CC=clang - else - CC=clang-3.8 - fi - AR=ar -else - echo "Invalid target specified on command line ${ARCH}" - exit 1 -fi - -export NEARBY=$(cd `dirname ${0}` && pwd) - -PLATFORM=$(uname -s | grep -i '\(mingw\|cygwin\)') -echo $PLATFORM - -make_args= -if [ ! -z "$NEARBY_MAKEFILE_DEBUG" ]; then - echo "NEARBY_MAKEFILE_DEBUG is set, passing -d to make" - make_args+=" -d" -fi - -make \ - $make_args \ - -C "${NEARBY}" \ - CC="${CC}" \ - AR="${AR}" \ - ARCH="${ARCH}" \ - $@ - -make_rc=$? - -# NOTE: if make fails, it is important that the bad return code is bubbled up -# to the caller of this script. -# We don't want automated processes to keep going if there was a build error. - -if [ $make_rc -ne 0 ]; then - exit $make_rc -fi diff --git a/embedded/client/source/nearby_fp_client.c b/embedded/client/source/nearby_fp_client.c deleted file mode 100644 index 0ee80dbb..00000000 --- a/embedded/client/source/nearby_fp_client.c +++ /dev/null @@ -1,2016 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 "nearby_fp_client.h" - -#include - -#include "nearby.h" -#include "nearby_assert.h" -#include "nearby_event.h" -#include "nearby_fp_library.h" -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -#include "nearby_platform_battery.h" -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ -#if NEARBY_FP_MESSAGE_STREAM -#include "nearby_message_stream.h" -#endif /* NEARBY_FP_MESSAGE_STREAM */ -#include "nearby_assert.h" -#include "nearby_platform_audio.h" -#include "nearby_platform_ble.h" -#include "nearby_platform_bt.h" -#include "nearby_platform_os.h" -#include "nearby_platform_persistence.h" -#include "nearby_platform_se.h" -#include "nearby_trace.h" -#include "nearby_utils.h" - -#define ENCRYPTED_REQUEST_LENGTH 16 -#define PUBLIC_KEY_LENGTH 64 -#define REQUEST_BT_ADDRESS_OFFSET 2 - -// block pairing attempts for 5 minutes after 10 failures -#define MAX_PAIRING_FAILURE_COUNT 10 -#define REJECT_PAIRING_TIMEOUT_MS (5 * 60 * 1000) -#define PASSKEY_MAX_WAIT_TIME_MS 10000 -#define WAIT_FOR_PAIRING_REQUEST_TIME_MS 10000 -#define ACCOUNT_KEY_WRITE_TIME_MS 60000 -#define RETRO_PAIRING_REQUEST_TIME_MS 60000 -// Defines the timeout when waiting for pairing result when the Seeker writes -// the Account Key before/during pairing. -#define WAIT_FOR_PAIRING_RESULT_AFTER_ACCOUNT_KEY_TIME_MS 60000 -#define KEY_BASED_PAIRING_REQUEST_FLAG 0x00 -#define ACTION_REQUEST_FLAG 0x10 - -// KBPR - Key Based Pairing Request -#define KBPR_INITIATE_PAIRING_MASK (1 << 6) -#define KBPR_NOTIFY_EXISTING_NAME_MASK (1 << 5) -#define KBPR_RETROACTIVELY_WRITE_ACCOUNT_KEY_MASK (1 << 4) -#define KBPR_SEEKER_SUPPORTS_BLE_DEVICES_MASK (1 << 3) -#define KBPR_SEEKER_ADDRESS_OFFSET 8 - -#define ACTION_REQUEST_DEVICE_ACTION_MASK (1 << 7) -#define ACTION_REQUEST_WILL_WRITE_DATA_CHARACTERISTIC_MASK (1 << 6) - -#define SEEKER_PASSKEY_MESSAGE_TYPE 0x02 -#define PROVIDER_PASSKEY_MESSAGE_TYPE 0x03 -#define ACCOUNT_KEY_WRITE_MESSAGE_TYPE 0x04 - -#define PERSONALIZED_NAME_DATA_ID 1 - -#define INVALID_BATTERY_LEVEL (-1) - -#define INVALID_PEER_ADDRESS 0 - -// One byte per left, right and charging case -#define BATTERY_LEVELS_SIZE 3 - -// Size of battery remaining time (16 bits) -#define BATTERY_TIME_SIZE 2 - -// Size of 'Message Stream PSM' Gatt response. -#define PSM_MESSAGE_LENGTH 3 - -// The BLE address should be rotated on average every 1024 seconds -#define ADDRESS_ROTATION_PERIOD_MS 1024000 - -// The maximum size of device bitmap. We require one bit per paired device -#define MAX_DEVICE_BITMAP_SIZE 4 - -// The maximum payload size for 'Notify connection status' message -#define MAX_NOTIFY_CONNECTION_STATUS_MESSAGE_SIZE \ - (3 + MAX_DEVICE_BITMAP_SIZE + SESSION_NONCE_SIZE) - -// Possible values of 'Active device flag' -#define SEEKER_IS_NOT_ACTIVE_DEVICE 0 -#define SEEKER_IS_ACTIVE_DEVICE 1 -#define SEEKER_IS_NON_SASS 2 - -#define SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT_NAME_OFFSET 2 -#define SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT_TARGET_THIS_DEVICE 1 -#define SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT_TARGET_ANOTHER_DEVICE 2 - -enum PairingState { - kPairingStateIdle, - kPairingStateWaitingForPairingRequest, - kPairingStateWaitingForPasskey, - kPairingStateWaitingForPairingResult, - kPairingStateWaitingForAccountKeyWrite, - kPairingStateWaitingForAdditionalData -} pairing_state; -static const nearby_fp_client_Callbacks* client_callbacks; -static unsigned int timeout_start_ms; -static uint8_t pairing_failure_count; -static unsigned int reject_pairing_time_start_ms; -static uint64_t peer_public_address; -static int advertisement_mode; -static nearby_platform_AccountKeyInfo account_key_info; -static nearby_platform_AccountKeyInfo pending_account_key_info; -static uint64_t gatt_peer_address; -static uint32_t address_rotation_timestamp; -static void* address_rotation_task = NULL; -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA -static uint8_t additional_data_id; -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ -#ifdef NEARBY_FP_ENABLE_SASS -static const uint16_t kSassVersion = 0x101; -static uint8_t sass_custom_data = 0; -#endif /* NEARBY_FP_ENABLE_SASS */ - -#define RETURN_IF_ERROR(X) \ - do { \ - nearby_platform_status status = X; \ - if (kNearbyStatusOK != status) return status; \ - } while (0) - -#define BIT(b) (1 << b) -#define ISSET(v, b) (v & BIT(b)) - -#if NEARBY_FP_MESSAGE_STREAM -// Callback triggered when a complete message is received over message stream -static void OnMessageReceived(uint64_t peer_address, - nearby_message_stream_Message* message); -static void SendBleAddressUpdatedToAll(); - -typedef struct { - nearby_message_stream_State state; - // Random session nonce generated by the provider. It is used to authenticate - // the seeker and prevent replay attacks - uint8_t session_nonce[SESSION_NONCE_SIZE]; - uint8_t in_use_account_key[ACCOUNT_KEY_SIZE_BYTES]; - uint8_t buffer[MAX_MESSAGE_STREAM_PAYLOAD_SIZE + - sizeof(nearby_message_stream_Metadata)]; - uint8_t capabilities; - uint8_t platform_type; - uint8_t platform_build; -} rfcomm_input; - -static void InitRfcommInput(uint64_t peer_address, rfcomm_input* input) { - memset(input, 0, sizeof(*input)); - input->state.peer_address = peer_address; - input->state.on_message_received = OnMessageReceived; - for (int i = 0; i < SESSION_NONCE_SIZE; i++) { - input->session_nonce[i] = nearby_platform_Rand(); - } - input->state.length = sizeof(input->buffer); - input->state.buffer = input->buffer; - // defaults to: companion app installed, silence mode supported - input->capabilities = BIT(MESSAGE_CODE_CAPABILITIES_COMPANION_APP_INSTALLED) | - BIT(MESSAGE_CODE_CAPABILITIES_SILENCE_MODE_SUPPORTED); - nearby_message_stream_Init(&input->state); -} - -static rfcomm_input rfcomm_inputs[NEARBY_MAX_RFCOMM_CONNECTIONS]; -#ifdef NEARBY_FP_ENABLE_SASS -static void UpdateAndNotifySass(const rfcomm_input* seeker); -#endif /* NEARBY_FP_ENABLE_SASS */ - -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -#if NEARBY_FP_RETROACTIVE_PAIRING -typedef struct { - uint64_t peer_public_address; - uint64_t peer_le_address; - unsigned int retroactive_pairing_time_start_ms; -} retroactive_pairing_peer; - -static retroactive_pairing_peer - retroactive_pairing_list[NEARBY_MAX_RETROACTIVE_PAIRING]; - -static bool AddRetroactivePairingPeer(uint64_t peer_address) { - for (int i = 0; i < NEARBY_MAX_RETROACTIVE_PAIRING; i++) { - retroactive_pairing_peer* peer = &retroactive_pairing_list[i]; - - if (nearby_platform_GetCurrentTimeMs() - - peer->retroactive_pairing_time_start_ms > - RETRO_PAIRING_REQUEST_TIME_MS) { - peer->peer_public_address = INVALID_PEER_ADDRESS; - peer->peer_le_address = INVALID_PEER_ADDRESS; - } - - if (peer->peer_public_address == peer_address) { - return false; - } - } - - for (int i = 0; i < NEARBY_MAX_RETROACTIVE_PAIRING; i++) { - retroactive_pairing_peer* peer = &retroactive_pairing_list[i]; - if (peer->peer_public_address == INVALID_PEER_ADDRESS) { - NEARBY_TRACE(INFO, "timer set for retroactive pairing"); - peer->peer_public_address = peer_address; - peer->retroactive_pairing_time_start_ms = - nearby_platform_GetCurrentTimeMs(); - return true; - } - } - return false; -} - -static bool SetRetroactivePairingPeerLe(uint64_t peer_public_address, - uint64_t peer_le_address) { - for (int i = 0; i < NEARBY_MAX_RETROACTIVE_PAIRING; i++) { - retroactive_pairing_peer* peer = &retroactive_pairing_list[i]; - if (peer->peer_public_address == peer_public_address) { - peer->peer_le_address = peer_le_address; - return true; - } - } - return false; -} - -static bool RetroactivePairingPeerPending(uint64_t peer_address) { - for (int i = 0; i < NEARBY_MAX_RETROACTIVE_PAIRING; i++) { - retroactive_pairing_peer* peer = &retroactive_pairing_list[i]; - if (peer->peer_public_address == peer_address || - peer->peer_le_address == peer_address) { - return true; - } - } - return false; -} - -static bool RetroactivePairingPeerTimeout(uint64_t peer_address) { - for (int i = 0; i < NEARBY_MAX_RETROACTIVE_PAIRING; i++) { - retroactive_pairing_peer* peer = &retroactive_pairing_list[i]; - if ((peer->peer_public_address == peer_address || - peer->peer_le_address == peer_address) && - (nearby_platform_GetCurrentTimeMs() - - peer->retroactive_pairing_time_start_ms > - RETRO_PAIRING_REQUEST_TIME_MS)) { - return true; - } - } - return false; -} - -static void RemoveRetroactivePairingPeer(uint64_t peer_address) { - for (int i = 0; i < NEARBY_MAX_RETROACTIVE_PAIRING; i++) { - retroactive_pairing_peer* peer = &retroactive_pairing_list[i]; - if (peer->peer_public_address == peer_address || - peer->peer_le_address == peer_address) { - peer->peer_public_address = INVALID_PEER_ADDRESS; - peer->peer_le_address = INVALID_PEER_ADDRESS; - } - } -} -#endif /* NEARBY_FP_RETROACTIVE_PAIRING */ - -static bool BtAddressMatch(uint8_t* a, uint8_t* b) { - return 0 == memcmp(a, b, BT_ADDRESS_LENGTH); -} - -static bool ShowPairingIndicator() { - return advertisement_mode & NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR; -} - -#ifdef NEARBY_FP_ENABLE_SASS - -static bool IsSassSeeker(const rfcomm_input* input) { - return input->state.peer_address != INVALID_PEER_ADDRESS && - input->in_use_account_key[0] == 4; -} - -static bool IsDeviceSass(uint64_t peer_address) { - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - rfcomm_input* input = &rfcomm_inputs[i]; - if (input->state.peer_address == peer_address) { - return IsSassSeeker(input); - } - } - return false; -} - -static uint8_t* FindInUseKey() { - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - rfcomm_input* input = &rfcomm_inputs[i]; - if (IsSassSeeker(input)) { - return input->in_use_account_key; - } - } - return NULL; -} - -static uint8_t GetCustomData() { return sass_custom_data; } -static void SetCustomData(uint8_t data) { sass_custom_data = data; } - -#endif /* NEARBY_FP_ENABLE_SASS */ - -static bool IncludeSass() { -#ifdef NEARBY_FP_ENABLE_SASS - return advertisement_mode & NEARBY_FP_ADVERTISEMENT_SASS; -#else - return false; -#endif /* NEARBY_FP_ENABLE_SASS */ -} - -static uint8_t* SelectInUseKey() { -#ifdef NEARBY_FP_ENABLE_SASS - return IncludeSass() ? FindInUseKey() : NULL; -#else - return NULL; -#endif /* NEARBY_FP_ENABLE_SASS */ -} - -static bool IsInPairingMode() { - return nearby_platform_IsInPairingMode() || - (pairing_state != kPairingStateIdle && - pairing_state != kPairingStateWaitingForAccountKeyWrite && - pairing_state != kPairingStateWaitingForAdditionalData); -} - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -static bool ShowBatteryIndicator() { - return advertisement_mode & NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR; -} - -static bool IncludeBatteryInfo() { - return advertisement_mode & NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO; -} - -// Gets battery info. Returns the input BatteryInfo or NULL on error. -static nearby_platform_BatteryInfo* PrepareBatteryInfo( - nearby_platform_BatteryInfo* battery_info) { - nearby_platform_status status; - - battery_info->is_charging = false; - battery_info->right_bud_battery_level = battery_info->left_bud_battery_level = - battery_info->charging_case_battery_level = INVALID_BATTERY_LEVEL; - battery_info->remaining_time_minutes = 0; - status = nearby_platform_GetBatteryInfo(battery_info); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "GetBatteryInfo() failed with error %d", status); - return NULL; - } - return battery_info; -} - -#if NEARBY_FP_MESSAGE_STREAM -static nearby_platform_status SendBatteryInfoMessage(uint64_t peer_address) { - uint8_t levels[BATTERY_LEVELS_SIZE]; - nearby_message_stream_Message message = { - .message_group = MESSAGE_GROUP_DEVICE_INFORMATION_EVENT, - .message_code = MESSAGE_CODE_BATTERY_UPDATED, - .length = sizeof(levels), - .data = levels}; - nearby_platform_BatteryInfo battery_info; - if (!PrepareBatteryInfo(&battery_info)) return kNearbyStatusOK; - - SerializeBatteryInfo(message.data, &battery_info); - return nearby_message_stream_Send(peer_address, &message); -} - -static nearby_platform_status SendBatteryTimeMessage(uint64_t peer_address) { - uint8_t time[BATTERY_TIME_SIZE]; - nearby_message_stream_Message message = { - .message_group = MESSAGE_GROUP_DEVICE_INFORMATION_EVENT, - .message_code = MESSAGE_CODE_REMAINING_BATTERY_TIME, - .length = 1, - .data = time}; - nearby_platform_BatteryInfo battery_info; - if (!PrepareBatteryInfo(&battery_info)) return kNearbyStatusOK; - - if (battery_info.remaining_time_minutes > 255) { - message.length = sizeof(int16_t); - message.data[0] = battery_info.remaining_time_minutes >> 8; - message.data[1] = battery_info.remaining_time_minutes & 0xff; - } else { - message.data[0] = battery_info.remaining_time_minutes; - } - return nearby_message_stream_Send(peer_address, &message); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -static void AccountKeyRejected() { - if (++pairing_failure_count == MAX_PAIRING_FAILURE_COUNT) { - reject_pairing_time_start_ms = nearby_platform_GetCurrentTimeMs(); - } -} - -static void DiscardAccountKey() { - memset(&account_key_info, 0, sizeof(account_key_info)); -} - -static bool ShouldTimeout(unsigned int timeout_ms) { - return nearby_platform_GetCurrentTimeMs() - timeout_start_ms > timeout_ms; -} - -static bool HasPendingAccountKey() { - return pending_account_key_info.account_key[0] == - ACCOUNT_KEY_WRITE_MESSAGE_TYPE; -} - -static void DiscardPendingAccountKey() { - memset(&pending_account_key_info, 0, sizeof(pending_account_key_info)); -} - -static void RotateBleAddress() { - address_rotation_timestamp = nearby_platform_GetCurrentTimeMs(); - nearby_platform_SetAdvertisement(NULL, 0, kDisabled); -#ifdef NEARBY_FP_HAVE_BLE_ADDRESS_ROTATION - uint64_t address = nearby_platform_RotateBleAddress(); - NEARBY_TRACE(INFO, "Rotated BLE address to: %s", - nearby_utils_MacToString(address)); -#else - unsigned i; - uint64_t address = 0; - for (i = 0; i < BT_ADDRESS_LENGTH; i++) { - address = (address << 8) ^ nearby_platform_Rand(); - } - address |= (uint64_t)1 << 46; - address &= ~((uint64_t)1 << 47); - NEARBY_TRACE(WARNING, "Rotate address to: %s", - nearby_utils_MacToString(address)); - nearby_platform_SetBleAddress(address); -#if NEARBY_FP_MESSAGE_STREAM - SendBleAddressUpdatedToAll(); -#endif -#endif /* NEARBY_FP_HAVE_BLE_ADDRESS_ROTATION */ -} - -static nearby_platform_status SendKeyBasedPairingResponse( - uint64_t peer_address, bool extended_response) { - nearby_platform_status status; - uint8_t raw[AES_MESSAGE_SIZE_BYTES], encrypted[AES_MESSAGE_SIZE_BYTES]; - nearby_fp_CreateRawKeybasedPairingResponse(raw, extended_response); - status = nearby_platform_Aes128Encrypt(raw, encrypted, - account_key_info.account_key); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "Failed to encrypt key-based pairing response"); - return status; - } - status = nearby_platform_GattNotify(peer_address, kKeyBasedPairing, encrypted, - sizeof(encrypted)); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "Failed to notify on key-based pairing response"); - } - return status; -} - -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA -static nearby_platform_status NotifyPersonalizedName(uint64_t peer_address) { - NEARBY_TRACE(VERBOSE, "NotifyPersonalizedName"); - uint8_t data[ADDITIONAL_DATA_HEADER_SIZE + PERSONALIZED_NAME_MAX_SIZE]; - size_t length = PERSONALIZED_NAME_MAX_SIZE; - nearby_platform_status status; - status = nearby_platform_LoadValue( - kStoredKeyPersonalizedName, data + ADDITIONAL_DATA_HEADER_SIZE, &length); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(WARNING, "Failed to load personalized name, status: %d", - status); - return status; - } - if (!length) { - NEARBY_TRACE(WARNING, "Empty personalized name"); - } - - length += ADDITIONAL_DATA_HEADER_SIZE; - status = nearby_fp_EncodeAdditionalData(data, length, - account_key_info.account_key); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(ERROR, "Failed to encrypt additional data, status: %d", - status); - return status; - } - status = - nearby_platform_GattNotify(peer_address, kAdditionalData, data, length); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(ERROR, "Failed to notify on additional data, status: %d", - status); - NEARBY_TRACE(ERROR, "Additional data: %s", - nearby_utils_ArrayToString(data, length)); - } - return kNearbyStatusOK; -} - -static nearby_platform_status SaveAdditionalData(const uint8_t* data, - size_t length) { - if (additional_data_id == PERSONALIZED_NAME_DATA_ID) { - char name[PERSONALIZED_NAME_MAX_SIZE * sizeof(uint8_t) / sizeof(char) + 1]; - memcpy(name, data, length); - name[length * sizeof(uint8_t) / sizeof(char)] = '\0'; - NEARBY_TRACE(INFO, "Saving personalized name: %s", name); - nearby_platform_SetDeviceName(name); - return nearby_platform_SaveValue(kStoredKeyPersonalizedName, data, length); - } - NEARBY_TRACE(WARNING, "Unsupported data id 0x%02x", additional_data_id); - return kNearbyStatusUnsupported; -} - -static nearby_platform_status OnAdditionalDataWrite(uint64_t peer_address, - const uint8_t* request, - size_t length) { - NEARBY_TRACE(VERBOSE, "OnAdditionalDataWrite"); - if (pairing_state != kPairingStateWaitingForAdditionalData) { - NEARBY_TRACE(WARNING, - "Not expecting a write to Additional Data. Current state: %d", - pairing_state); - return kNearbyStatusError; - } - nearby_platform_status status = nearby_fp_DecodeAdditionalData( - (uint8_t*)request, length, account_key_info.account_key); - DiscardAccountKey(); - if (kNearbyStatusOK == status) { - status = SaveAdditionalData(request + ADDITIONAL_DATA_HEADER_SIZE, - length - ADDITIONAL_DATA_HEADER_SIZE); - } - pairing_state = kPairingStateIdle; - return status; -} -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ - -static nearby_platform_status HandleKeyBasedPairingRequest( - uint64_t peer_address, uint8_t request[ENCRYPTED_REQUEST_LENGTH]) { - NEARBY_TRACE(VERBOSE, "HandleKeyBasedPairingRequest"); - int flags; - flags = request[1]; -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA - if (flags & KBPR_NOTIFY_EXISTING_NAME_MASK) { - NotifyPersonalizedName(peer_address); - } -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ - - if (flags & KBPR_RETROACTIVELY_WRITE_ACCOUNT_KEY_MASK) { - if (flags & KBPR_INITIATE_PAIRING_MASK) { - NEARBY_TRACE(WARNING, - "received flag Initiate pairing in retroactive pairing"); - } - -#if NEARBY_FP_RETROACTIVE_PAIRING - uint64_t peer_public_address = - nearby_utils_GetBigEndian48(request + KBPR_SEEKER_ADDRESS_OFFSET); - - if (RetroactivePairingPeerPending(peer_public_address) == false) { - NEARBY_TRACE( - ERROR, "Ignoring retroactive pairing request from unexpected client"); - RemoveRetroactivePairingPeer(peer_public_address); - return kNearbyStatusError; - } - - if (SetRetroactivePairingPeerLe(peer_public_address, peer_address) == - false) { - NEARBY_TRACE(ERROR, "Cannot set le address for retroactive pairing"); - RemoveRetroactivePairingPeer(peer_public_address); - return kNearbyStatusError; - } - - return kNearbyStatusOK; -#else - return kNearbyStatusUnsupported; -#endif /* NEARBY_FP_RETROACTIVE_PAIRING */ - } - - nearby_platform_SetFastPairCapabilities(); - if (flags & KBPR_INITIATE_PAIRING_MASK) { - peer_public_address = - nearby_utils_GetBigEndian48(request + KBPR_SEEKER_ADDRESS_OFFSET); - NEARBY_TRACE(INFO, "Send pairing request to %s", - nearby_utils_MacToString(peer_public_address)); - nearby_platform_SendPairingRequest(peer_public_address); - pairing_state = kPairingStateWaitingForPasskey; - } else { - pairing_state = kPairingStateWaitingForPairingRequest; - timeout_start_ms = nearby_platform_GetCurrentTimeMs(); - } - return kNearbyStatusOK; -} - -static nearby_platform_status HandleActionRequest( - uint64_t peer_address, uint8_t request[ENCRYPTED_REQUEST_LENGTH]) { - NEARBY_TRACE(VERBOSE, "HandleActionRequest"); - int flags; - flags = request[1]; - if (flags & ACTION_REQUEST_DEVICE_ACTION_MASK) { - NEARBY_TRACE(VERBOSE, "Device action not implemented"); - return kNearbyStatusUnimplemented; - } -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA - if (flags & ACTION_REQUEST_WILL_WRITE_DATA_CHARACTERISTIC_MASK) { - pairing_state = kPairingStateWaitingForAdditionalData; - additional_data_id = request[10]; - } - return kNearbyStatusOK; -#else - return kNearbyStatusUnsupported; -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ -} - -static nearby_platform_status OnWriteKeyBasedPairing(uint64_t peer_address, - const uint8_t* request, - size_t length) { - nearby_platform_status status; - uint8_t decrypted_request[ENCRYPTED_REQUEST_LENGTH]; - uint8_t ble_address[BT_ADDRESS_LENGTH]; - uint8_t public_address[BT_ADDRESS_LENGTH]; - - NEARBY_TRACE(VERBOSE, "OnWriteKeyBasedPairing"); - if (pairing_failure_count >= MAX_PAIRING_FAILURE_COUNT) { - unsigned int current_time = nearby_platform_GetCurrentTimeMs(); - if (current_time - reject_pairing_time_start_ms < - REJECT_PAIRING_TIMEOUT_MS) { - NEARBY_TRACE(INFO, "Too many failed pairing attempts"); - return kNearbyStatusOK; - } else { - NEARBY_TRACE(INFO, "Timeout expired. Allow pairing attempts"); - pairing_failure_count = 0; - } - } - nearby_utils_CopyBigEndian(ble_address, nearby_platform_GetBleAddress(), - BT_ADDRESS_LENGTH); - nearby_utils_CopyBigEndian(public_address, nearby_platform_GetPublicAddress(), - BT_ADDRESS_LENGTH); - // When the device is nondiscoverable, accept a saved account key. - // or accept a new account key for retroactive pairing - // When the device is discoverable, we can accept a new account key too. - if (length == ENCRYPTED_REQUEST_LENGTH + PUBLIC_KEY_LENGTH) { - uint8_t key[ACCOUNT_KEY_SIZE_BYTES]; - uint8_t remote_public_key[PUBLIC_KEY_LENGTH]; - memcpy(remote_public_key, request + ENCRYPTED_REQUEST_LENGTH, - PUBLIC_KEY_LENGTH); - status = nearby_fp_CreateSharedSecret(remote_public_key, key); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "Failed to create shared key, error: %d", status); - NEARBY_TRACE( - ERROR, "Remote public key: %s", - nearby_utils_ArrayToString(remote_public_key, PUBLIC_KEY_LENGTH)); - return status; - } - status = nearby_platform_Aes128Decrypt(request, decrypted_request, key); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "Failed to decrypt request, error: %d", status); - return status; - } - if (!BtAddressMatch(ble_address, - decrypted_request + REQUEST_BT_ADDRESS_OFFSET) && - !BtAddressMatch(public_address, - decrypted_request + REQUEST_BT_ADDRESS_OFFSET)) { - NEARBY_TRACE(INFO, "Invalid incoming BT address %s", - nearby_utils_ArrayToString(decrypted_request, 6)); - AccountKeyRejected(); - return kNearbyStatusOK; - } - memcpy(account_key_info.account_key, key, ACCOUNT_KEY_SIZE_BYTES); -#ifdef NEARBY_FP_ENABLE_SASS - account_key_info.peer_address = peer_address; -#endif /* NEARBY_FP_ENABLE_SASS */ - } else if (length == ENCRYPTED_REQUEST_LENGTH) { - // try each key in the persisted Account Key List - int num_keys = nearby_fp_GetAccountKeyCount(); - int i; - for (i = 0; i < num_keys; i++) { - const nearby_platform_AccountKeyInfo* key = nearby_fp_GetAccountKey(i); - status = nearby_platform_Aes128Decrypt(request, decrypted_request, - key->account_key); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "Failed to decrypt request, error: %d", status); - return status; - } - if (BtAddressMatch(ble_address, - decrypted_request + REQUEST_BT_ADDRESS_OFFSET) || - BtAddressMatch(public_address, - decrypted_request + REQUEST_BT_ADDRESS_OFFSET)) { - NEARBY_TRACE(VERBOSE, "Matched key number: %d", i); - nearby_fp_CopyAccountKey(&account_key_info, i); -#ifdef NEARBY_FP_ENABLE_SASS - // The existing account key could be for a different peer, so let's - // add it again with the current peer address - account_key_info.peer_address = peer_address; -#endif /* NEARBY_FP_ENABLE_SASS */ - nearby_fp_AddAccountKey(&account_key_info); - nearby_fp_SaveAccountKeys(); - break; - } - } - if (i == num_keys) { - NEARBY_TRACE(VERBOSE, "No key matched"); - AccountKeyRejected(); - return kNearbyStatusOK; - } - } else { - NEARBY_TRACE(WARNING, - "Unexpected key based pairing request length %d Request: %s", - length, nearby_utils_ArrayToString(request, length)); - return kNearbyStatusError; - } - pairing_failure_count = 0; - gatt_peer_address = peer_address; - - DiscardPendingAccountKey(); - - bool extended_response = - decrypted_request[0] == KEY_BASED_PAIRING_REQUEST_FLAG && - decrypted_request[1] & KBPR_SEEKER_SUPPORTS_BLE_DEVICES_MASK; - status = SendKeyBasedPairingResponse(peer_address, extended_response); - if (status != kNearbyStatusOK) return status; - - // TODO(jsobczak): Note that at the end of the packet there is a salt - // attached. When possible, these salts should be tracked, and if the - // Provider receives a request containing an already used salt, the request - // should be ignored to prevent replay attacks. - if (decrypted_request[0] == KEY_BASED_PAIRING_REQUEST_FLAG) { - return HandleKeyBasedPairingRequest(peer_address, decrypted_request); - } else if (decrypted_request[0] == ACTION_REQUEST_FLAG) { - return HandleActionRequest(peer_address, decrypted_request); - } - return kNearbyStatusOK; -} - -static nearby_platform_status NotifyProviderPasskey(uint64_t peer_address) { - uint8_t raw_passkey_block[AES_MESSAGE_SIZE_BYTES]; - uint8_t encrypted[AES_MESSAGE_SIZE_BYTES]; - uint32_t provider_passkey; - nearby_platform_status status; - provider_passkey = nearby_platfrom_GetPairingPassKey(); - - raw_passkey_block[0] = PROVIDER_PASSKEY_MESSAGE_TYPE; - nearby_utils_CopyBigEndian(raw_passkey_block + 1, provider_passkey, 3); - int i; - for (i = 4; i < AES_MESSAGE_SIZE_BYTES; i++) { - raw_passkey_block[i] = nearby_platform_Rand(); - } - status = nearby_platform_Aes128Encrypt(raw_passkey_block, encrypted, - account_key_info.account_key); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "Failed to encrypt passkey block"); - return status; - } - status = nearby_platform_GattNotify(peer_address, kPasskey, encrypted, - sizeof(encrypted)); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, - "Failed to notify on passkey characteristic, " - "Peer address: %s Encrypted: %s", - nearby_utils_MacToString(peer_address), - nearby_utils_ArrayToString(encrypted, sizeof(encrypted))); - } - return status; -} - -static nearby_platform_status OnPasskeyWrite(uint64_t peer_address, - const uint8_t* request, - size_t length) { - NEARBY_TRACE(VERBOSE, "OnPasskeyWrite"); - uint8_t raw_passkey_block[AES_MESSAGE_SIZE_BYTES]; - nearby_platform_status status; - uint32_t seeker_passkey; - if (pairing_state != kPairingStateWaitingForPasskey) { - NEARBY_TRACE(INFO, "Not expecting a passkey write. Current state: %d", - pairing_state); - return kNearbyStatusError; - } - if (gatt_peer_address != peer_address) { - NEARBY_TRACE(INFO, - "Ignoring passkey write from unexpected client, expected GATT " - "peer address: %s", - nearby_utils_MacToString(gatt_peer_address)); - NEARBY_TRACE(INFO, "Peer address: %s", - nearby_utils_MacToString(peer_address)); - return kNearbyStatusError; - } - if (ShouldTimeout(PASSKEY_MAX_WAIT_TIME_MS)) { - NEARBY_TRACE(INFO, "Not expecting a passkey write"); - return kNearbyStatusTimeout; - } - if (length != AES_MESSAGE_SIZE_BYTES) { - NEARBY_TRACE(INFO, "Passkey: expected %d bytes, got %d request: %s", - AES_MESSAGE_SIZE_BYTES, length, - nearby_utils_ArrayToString(request, length)); - return kNearbyStatusError; - } - status = nearby_platform_Aes128Decrypt(request, raw_passkey_block, - account_key_info.account_key); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(WARNING, "Failed to decrypt passkey block"); - DiscardAccountKey(); - return status; - } - if (raw_passkey_block[0] != SEEKER_PASSKEY_MESSAGE_TYPE) { - NEARBY_TRACE(WARNING, "Unexpected passkey message type 0x%x", - raw_passkey_block[0]); - return kNearbyStatusError; - } - pairing_state = kPairingStateWaitingForPairingResult; - NotifyProviderPasskey(peer_address); - seeker_passkey = nearby_utils_GetBigEndian24(raw_passkey_block + 1); - nearby_platform_SetRemotePasskey(seeker_passkey); - return kNearbyStatusOK; -} - -static nearby_platform_status SetNonDiscoverableAdvertisement() { - uint8_t advertisement[NON_DISCOVERABLE_ADV_SIZE_BYTES]; - const uint8_t* in_use_key = SelectInUseKey(); - size_t length; -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION - nearby_platform_BatteryInfo battery_info; - length = nearby_fp_CreateNondiscoverableAdvertisementWithBattery( - advertisement, sizeof(advertisement), ShowPairingIndicator(), - ShowBatteryIndicator(), - IncludeBatteryInfo() ? PrepareBatteryInfo(&battery_info) : NULL); -#else - length = nearby_fp_CreateNondiscoverableAdvertisement( - advertisement, sizeof(advertisement), ShowPairingIndicator()); -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ -#ifdef NEARBY_FP_ENABLE_SASS - if (IncludeSass() && (nearby_fp_GetAccountKeyCount() > 0)) { - uint8_t device_bitmap[MAX_DEVICE_BITMAP_SIZE]; - size_t device_bitmap_length = sizeof(device_bitmap); - // Use either the in-use key or the most recently used account key - const uint8_t* key = - in_use_key ? in_use_key : nearby_fp_GetAccountKey(0)->account_key; - NEARBY_ASSERT(key != NULL); - nearby_platform_GetConnectionBitmap(device_bitmap, &device_bitmap_length); - size_t sass_length = nearby_fp_GenerateSassAdvertisement( - advertisement + length + RRF_HEADER_SIZE, - sizeof(advertisement) - length - RRF_HEADER_SIZE, - nearby_fp_GetSassConnectionState(), GetCustomData(), device_bitmap, - device_bitmap_length); - RETURN_IF_ERROR(nearby_fp_EncryptRandomResolvableField( - advertisement + length, RRF_HEADER_SIZE + sass_length, key, - nearby_fp_FindLtv(advertisement, SALT_FIELD_TYPE))); - length += RRF_HEADER_SIZE + sass_length; - // Update FP advertisement length - advertisement[0] = length - 1; - } -#endif /* NEARBY_FP_ENABLE_SASS */ - nearby_fp_SetBloomFilter(advertisement, IncludeSass(), in_use_key); - - length += nearby_fp_AppendTxPower(advertisement + length, - sizeof(advertisement) - length, - nearby_platform_GetTxLevel()); - return nearby_platform_SetAdvertisement(advertisement, length, - kNoLargerThan250ms); -} - -// Steps executed after successful pairing with a seeker and receiving the -// account key. -static void RunPostPairingSteps( - uint64_t peer_address, const nearby_platform_AccountKeyInfo* account_key) { - nearby_fp_AddAccountKey(account_key); - nearby_fp_SaveAccountKeys(); - DiscardPendingAccountKey(); -#if NEARBY_FP_RETROACTIVE_PAIRING - if (RetroactivePairingPeerPending(peer_address)) { - RemoveRetroactivePairingPeer(peer_address); - - if (RetroactivePairingPeerPending(peer_address)) { - NEARBY_TRACE(WARNING, "peer is still pending %s", - nearby_utils_MacToString(peer_address)); - } - if (pairing_state != kPairingStateIdle) { - NEARBY_TRACE(WARNING, - "Another fp pairing process has launched, do not change " - "pairing state"); - return; - } - } -#endif /* NEARBY_FP_RETROACTIVE_PAIRING */ - - pairing_state = kPairingStateIdle; -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA - pairing_state = kPairingStateWaitingForAdditionalData; - additional_data_id = PERSONALIZED_NAME_DATA_ID; -#endif - if (advertisement_mode & NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE) { - NEARBY_TRACE(INFO, "Account key added, update advertisement"); - nearby_platform_SetAdvertisement(NULL, 0, kDisabled); - SetNonDiscoverableAdvertisement(); - } -} -static nearby_platform_status OnAccountKeyWrite(uint64_t peer_address, - const uint8_t* request, - size_t length) { - NEARBY_TRACE(VERBOSE, "OnAccountKeyWrite"); - nearby_platform_AccountKeyInfo key_info; - uint8_t* decrypted_request = key_info.account_key; - nearby_platform_status status; - bool wait_until_paired = false; - -#if NEARBY_FP_RETROACTIVE_PAIRING - if (RetroactivePairingPeerPending(peer_address)) { - if (RetroactivePairingPeerTimeout(peer_address)) { - NEARBY_TRACE(ERROR, - "Not expecting an retroactive pairing request. Timeout. " - "Peer address: %s", - nearby_utils_MacToString(peer_address)); - RemoveRetroactivePairingPeer(peer_address); - return kNearbyStatusTimeout; - } - } else { -#endif /* NEARBY_FP_RETROACTIVE_PAIRING */ - if (pairing_state == kPairingStateWaitingForPairingRequest || - pairing_state == kPairingStateWaitingForPairingResult || - pairing_state == kPairingStateWaitingForPasskey) { - NEARBY_TRACE(VERBOSE, "Account key write before paired event"); - wait_until_paired = true; - } else if (pairing_state != kPairingStateWaitingForAccountKeyWrite) { - NEARBY_TRACE(INFO, - "Not expecting an account key write. Current state: %d", - pairing_state); - return kNearbyStatusError; - } - if (gatt_peer_address != peer_address && - peer_public_address != peer_address) { - NEARBY_TRACE(INFO, "Ignoring account key write from unexpected client"); - NEARBY_TRACE(ERROR, "Peer address: %s", - nearby_utils_MacToString(peer_address)); - NEARBY_TRACE(ERROR, "Expected BLE peer address: %s", - nearby_utils_MacToString(gatt_peer_address)); - NEARBY_TRACE(ERROR, "Expected BT peer address: %s", - nearby_utils_MacToString(peer_public_address)); - return kNearbyStatusError; - } - - if (ShouldTimeout(ACCOUNT_KEY_WRITE_TIME_MS)) { - NEARBY_TRACE(INFO, "Not expecting an account key write. Timeout"); - return kNearbyStatusTimeout; - } -#if NEARBY_FP_RETROACTIVE_PAIRING - } -#endif /* NEARBY_FP_RETROACTIVE_PAIRING */ - if (length != AES_MESSAGE_SIZE_BYTES) { - NEARBY_TRACE(INFO, "Account key: expected %d bytes, got %d", - AES_MESSAGE_SIZE_BYTES, length); - return kNearbyStatusError; - } - status = nearby_platform_Aes128Decrypt(request, decrypted_request, - account_key_info.account_key); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(WARNING, "Failed to decrypt account key block"); - return status; - } - if (decrypted_request[0] != ACCOUNT_KEY_WRITE_MESSAGE_TYPE) { - NEARBY_TRACE(WARNING, "Unexpected account key message type 0x%x", - decrypted_request[0]); - return kNearbyStatusError; - } -#ifdef NEARBY_FP_ENABLE_SASS - key_info.peer_address = peer_address; -#endif /* NEARBY_FP_ENABLE_SASS */ - if (wait_until_paired) { - memcpy(pending_account_key_info.account_key, decrypted_request, - ACCOUNT_KEY_SIZE_BYTES); - nearby_platform_StartTimer( - DiscardPendingAccountKey, - WAIT_FOR_PAIRING_RESULT_AFTER_ACCOUNT_KEY_TIME_MS); - return kNearbyStatusOK; - } - RunPostPairingSteps(peer_address, &key_info); - return kNearbyStatusOK; -} - -static nearby_platform_status OnGattWrite( - uint64_t peer_address, nearby_fp_Characteristic characteristic, - const uint8_t* request, size_t length) { - switch (characteristic) { - case kKeyBasedPairing: - return OnWriteKeyBasedPairing(peer_address, request, length); - case kPasskey: - return OnPasskeyWrite(peer_address, request, length); - case kAccountKey: - return OnAccountKeyWrite(peer_address, request, length); - case kAdditionalData: -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA - return OnAdditionalDataWrite(peer_address, request, length); -#else - break; -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ - case kMessageStreamPsm: - case kModelId: - case kFirmwareRevision: - break; - } - NEARBY_TRACE(ERROR, - "Characteristic unsupported: Peer address: %s Characteristic: " - "%d Request: %s", - nearby_utils_MacToString(peer_address), characteristic, - nearby_utils_ArrayToString(request, length)); - return kNearbyStatusUnsupported; -} - -static int32_t GetMessageStreamPsm() { -#if NEARBY_FP_PREFER_LE_TRANSPORT - return nearby_platform_GetMessageStreamPsm(); -#else - return -1; -#endif /* NEARBY_FP_PREFER_LE_TRANSPORT */ -} - -static nearby_platform_status OnMesssageStreamPsmRead(uint8_t* output, - size_t* length) { - int32_t psm = GetMessageStreamPsm(); - if (*length < PSM_MESSAGE_LENGTH) { - return kNearbyStatusError; - } - memset(output, 0, PSM_MESSAGE_LENGTH); - *length = PSM_MESSAGE_LENGTH; - if (psm >= 0 && psm <= 0xFFFF) { - output[0] = 1; - output[1] = psm >> 8; - output[2] = psm; - } - return kNearbyStatusOK; -} - -static nearby_platform_status OnGattRead( - uint64_t peer_address, nearby_fp_Characteristic characteristic, - uint8_t* output, size_t* length) { - switch (characteristic) { - case kModelId: - return nearby_fp_GattReadModelId(output, length); - case kMessageStreamPsm: - return OnMesssageStreamPsmRead(output, length); - case kKeyBasedPairing: - case kPasskey: - case kAccountKey: - case kFirmwareRevision: - case kAdditionalData: - break; - } - return kNearbyStatusUnsupported; -} - -static void OnPairingRequest(uint64_t peer_address) { - NEARBY_TRACE(VERBOSE, "Pairing request from %s", - nearby_utils_MacToString(peer_address)); - if (pairing_state == kPairingStateWaitingForPairingRequest) { - if (ShouldTimeout(WAIT_FOR_PAIRING_REQUEST_TIME_MS)) { - pairing_state = kPairingStateIdle; - } else { - pairing_state = kPairingStateWaitingForPasskey; - peer_public_address = peer_address; - timeout_start_ms = nearby_platform_GetCurrentTimeMs(); - } - } -} - -static void OnPaired(uint64_t peer_address) { - NEARBY_TRACE(INFO, "Paired with %s", nearby_utils_MacToString(peer_address)); - if (peer_public_address == peer_address && HasPendingAccountKey()) { - NEARBY_TRACE(INFO, "Saving pending account key"); - RunPostPairingSteps(peer_address, &pending_account_key_info); - return; - } - peer_public_address = peer_address; - if (pairing_state == kPairingStateWaitingForPairingResult) { - pairing_state = kPairingStateWaitingForAccountKeyWrite; - timeout_start_ms = nearby_platform_GetCurrentTimeMs(); - } -#if NEARBY_FP_RETROACTIVE_PAIRING - else if (AddRetroactivePairingPeer(peer_address) == false) { - NEARBY_TRACE(WARNING, "No more timer for retroactive pairing"); - } -#endif /* NEARBY_FP_RETROACTIVE_AIRING */ -} - -static void OnPairingFailed(uint64_t peer_address) { - NEARBY_TRACE(ERROR, "Pairing failed with %s", - nearby_utils_MacToString(peer_address)); - DiscardAccountKey(); - DiscardPendingAccountKey(); -} - -#if NEARBY_FP_MESSAGE_STREAM -// Finds and initializes an unused |rfcomm_input|. Returns NULL if not found. -static rfcomm_input* FindAvailableRfcommInput(uint64_t peer_address) { - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - rfcomm_input* input = &rfcomm_inputs[i]; - if (input->state.peer_address == INVALID_PEER_ADDRESS || - input->state.peer_address == peer_address) { - InitRfcommInput(peer_address, input); - return input; - } - } - return NULL; -} - -// Gets |rfcomm_input| for |peer_address|. Returns NULL if not found. -static rfcomm_input* GetRfcommInput(uint64_t peer_address) { - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - if (rfcomm_inputs[i].state.peer_address == peer_address) { - return &rfcomm_inputs[i]; - } - } - return NULL; -} - -nearby_platform_status nearby_fp_client_SetSilenceMode(uint64_t peer_address, - bool enable) { - rfcomm_input* input = GetRfcommInput(peer_address); - if (!input) { - return kNearbyStatusError; - } - nearby_message_stream_Message message = { - .message_group = MESSAGE_GROUP_BLUETOOTH, - .message_code = MESSAGE_CODE_DISABLE_SILENCE_MODE, - .length = 0}; - if (enable) message.message_code = MESSAGE_CODE_ENABLE_SILENCE_MODE; - if (!input) { - return kNearbyStatusError; - } - if (!ISSET(input->capabilities, - MESSAGE_CODE_CAPABILITIES_SILENCE_MODE_SUPPORTED)) { - return kNearbyStatusUnsupported; - } - return nearby_message_stream_Send(peer_address, &message); -} - -nearby_platform_status nearby_fp_client_SignalLogBufferFull( - uint64_t peer_address) { - rfcomm_input* input = GetRfcommInput(peer_address); - if (!input) { - return kNearbyStatusError; - } - if (!ISSET(input->capabilities, - MESSAGE_CODE_CAPABILITIES_COMPANION_APP_INSTALLED)) { - return kNearbyStatusOK; - } - nearby_message_stream_Message message = { - .message_group = MESSAGE_GROUP_COMPANION_APP_EVENT, - .message_code = MESSAGE_CODE_LOG_BUFFER_FULL, - .length = 0}; - return nearby_message_stream_Send(peer_address, &message); -} - -static nearby_platform_status SendBleAddressUpdated(uint64_t peer_address) { - uint8_t buffer[BT_ADDRESS_LENGTH]; - nearby_message_stream_Message message = { - .message_group = MESSAGE_GROUP_DEVICE_INFORMATION_EVENT, - .message_code = MESSAGE_CODE_BLE_ADDRESS_UPDATED, - .length = BT_ADDRESS_LENGTH, - .data = buffer}; - nearby_utils_CopyBigEndian(message.data, nearby_platform_GetBleAddress(), - BT_ADDRESS_LENGTH); - return nearby_message_stream_Send(peer_address, &message); -} - -static void SendBleAddressUpdatedToAll() { - uint8_t buffer[BT_ADDRESS_LENGTH]; - nearby_message_stream_Message message = { - .message_group = MESSAGE_GROUP_DEVICE_INFORMATION_EVENT, - .message_code = MESSAGE_CODE_BLE_ADDRESS_UPDATED, - .length = BT_ADDRESS_LENGTH, - .data = buffer}; - nearby_utils_CopyBigEndian(message.data, nearby_platform_GetBleAddress(), - BT_ADDRESS_LENGTH); - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - rfcomm_input* input = &rfcomm_inputs[i]; - if (input->state.peer_address != INVALID_PEER_ADDRESS) { - nearby_message_stream_Send(input->state.peer_address, &message); - } - } -} - -static void OnMessageStreamConnected(uint64_t peer_address) { - nearby_platform_status status; - uint8_t buffer[MAX_MESSAGE_STREAM_PAYLOAD_SIZE]; - nearby_message_stream_Message message; - size_t length = sizeof(buffer); - rfcomm_input* input; - - NEARBY_TRACE(VERBOSE, "OnMessageStreamConnected %s", - nearby_utils_MacToString(peer_address)); - input = FindAvailableRfcommInput(peer_address); - if (!input) { - NEARBY_TRACE(WARNING, "Too many concurrent RFCOMM connections"); - return; - } - - message.data = buffer; - nearby_fp_GattReadModelId(message.data, &length); - message.length = length; - message.message_group = MESSAGE_GROUP_DEVICE_INFORMATION_EVENT; - message.message_code = MESSAGE_CODE_MODEL_ID; - - status = nearby_message_stream_Send(peer_address, &message); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(ERROR, "Failed to send model id, status: %d Peer address: %s", - status, nearby_utils_MacToString(peer_address)); - return; - } - status = SendBleAddressUpdated(peer_address); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(ERROR, - "Failed to send ble address, status: %d Peer address: %s", - status, nearby_utils_MacToString(peer_address)); - return; - } - - // Send session nonce - message.message_code = MESSAGE_CODE_SESSION_NONCE; - message.length = SESSION_NONCE_SIZE; - message.data = input->session_nonce; - status = nearby_message_stream_Send(peer_address, &message); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(ERROR, "Failed to send session nonce, status: %d", status); - return; - } - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION - status = SendBatteryInfoMessage(peer_address); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(ERROR, - "Failed to send battery info, status: %d Peer address: %s", - status, nearby_utils_MacToString(peer_address)); - return; - } - status = SendBatteryTimeMessage(peer_address); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(ERROR, - "Failed to send battery info, status: %d Peer address: %s", - status, nearby_utils_MacToString(peer_address)); - return; - } -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - - if (client_callbacks != NULL && client_callbacks->on_event != NULL) { - nearby_event_MessageStreamConnected payload = {.peer_address = - peer_address}; - nearby_event_Event event = { - .event_type = kNearbyEventMessageStreamConnected, - .payload = (uint8_t*)&payload}; - client_callbacks->on_event(&event); - } -} - -static void OnMessageStreamDisconnected(uint64_t peer_address) { - rfcomm_input* input; - - NEARBY_TRACE(VERBOSE, "OnMessageStreamDisconnected %s", - nearby_utils_MacToString(peer_address)); - input = GetRfcommInput(peer_address); - if (!input) { - NEARBY_TRACE(WARNING, "Unexpected disconnection from %s", - nearby_utils_MacToString(peer_address)); - return; - } -#ifdef NEARBY_FP_ENABLE_SASS - bool update_advert = IncludeSass() && IsSassSeeker(input); -#endif /* NEARBY_FP_ENABLE_SASS */ - input->state.peer_address = INVALID_PEER_ADDRESS; - - if (client_callbacks != NULL && client_callbacks->on_event != NULL) { - nearby_event_MessageStreamDisconnected payload = {.peer_address = - peer_address}; - nearby_event_Event event = { - .event_type = kNearbyEventMessageStreamDisconnected, - .payload = (uint8_t*)&payload}; - client_callbacks->on_event(&event); - } -#if NEARBY_FP_RETROACTIVE_PAIRING - RemoveRetroactivePairingPeer(peer_address); -#endif /*NEARBY_FP_RETROACTIVE_PAIRING */ -#ifdef NEARBY_FP_ENABLE_SASS - if (update_advert) { - UpdateAndNotifySass(NULL); - } -#endif /* NEARBY_FP_ENABLE_SASS */ -} - -static void OnMessageStreamReceived(uint64_t peer_address, - const uint8_t* message, size_t length) { - rfcomm_input* input = GetRfcommInput(peer_address); - if (!input) { - NEARBY_TRACE(WARNING, "Unexpected RFCOMM message from %s", - nearby_utils_MacToString(peer_address)); - return; - } - nearby_message_stream_Read(&input->state, message, length); -} - -static nearby_platform_status VerifyMessageLength( - uint64_t peer_address, const nearby_message_stream_Message* message, - size_t expected_length) { - if (message->length != expected_length) { - NEARBY_TRACE(WARNING, "Invalid message(%d) length %d, expected %d", - message->message_code, message->length, expected_length); - nearby_message_stream_SendNack(peer_address, message, - /* fail reason= */ 0); - return kNearbyStatusInvalidInput; - } - return kNearbyStatusOK; -} - -// Sends either ACK or NACK response depending on |status| -static nearby_platform_status SendResponse( - uint64_t peer_address, const nearby_message_stream_Message* message, - nearby_platform_status status) { - if (kNearbyStatusOK == status) { - return nearby_message_stream_SendAck(peer_address, message); - } else { - // TODO(jsobczak): What should be the default fail reason? - uint8_t fail_reason = status == kNearbyStatusRedundantAction - ? FAIL_REASON_REDUNDANT_DEVICE_ACTION - : 0; - return nearby_message_stream_SendNack(peer_address, message, fail_reason); - } -} - -#ifdef NEARBY_FP_ENABLE_SASS -static uint8_t GetActiveDeviceFlag(uint64_t peer_address) { - uint64_t active_address = nearby_platform_GetActiveAudioSource(); - if (IsDeviceSass(active_address) == false && active_address != 0x0) { - return SEEKER_IS_NON_SASS; - } else if (peer_address == active_address) { - return SEEKER_IS_ACTIVE_DEVICE; - } else { - return SEEKER_IS_NOT_ACTIVE_DEVICE; - } -} - -static nearby_platform_status PrepareNotifyConnectionStatus( - nearby_message_stream_Message* message, rfcomm_input* input) { - size_t device_bitmap_length = MAX_DEVICE_BITMAP_SIZE; - NEARBY_ASSERT(message->length >= MAX_NOTIFY_CONNECTION_STATUS_MESSAGE_SIZE); - uint8_t iv[AES_MESSAGE_SIZE_BYTES]; - memcpy(iv, input->session_nonce, SESSION_NONCE_SIZE); - for (int i = SESSION_NONCE_SIZE; i < AES_MESSAGE_SIZE_BYTES; i++) { - iv[i] = nearby_platform_Rand(); - } - size_t offset = 0; - message->message_code = MESSAGE_CODE_SASS_NOTIFY_CONNECTION_STATUS; - message->data[offset++] = GetActiveDeviceFlag(input->state.peer_address); - message->data[offset++] = nearby_fp_GetSassConnectionState(); - message->data[offset++] = GetCustomData(); - - nearby_platform_GetConnectionBitmap(message->data + offset, - &device_bitmap_length); - offset += device_bitmap_length; - memcpy(message->data + offset, iv + SESSION_NONCE_SIZE, SESSION_NONCE_SIZE); - // The first byte of |data| is not encrypted. - RETURN_IF_ERROR(nearby_fp_AesEncryptIv(message->data + 1, offset - 1, iv, - input->in_use_account_key)); - message->length = offset + SESSION_NONCE_SIZE; - return kNearbyStatusOK; -} - -static bool IsSameAccountKey(const rfcomm_input* a, const rfcomm_input* b) { - return a == b || (a != NULL && b != NULL && - memcmp(a->in_use_account_key, b->in_use_account_key, - ACCOUNT_KEY_SIZE_BYTES) == 0); -} - -static bool UsesInUseAccountKey(const rfcomm_input* input, - const uint8_t* account_key) { - return input != NULL && account_key != NULL && - memcmp(input->in_use_account_key, account_key, - ACCOUNT_KEY_SIZE_BYTES) == 0; -} - -static nearby_platform_status NotifySassConnectionStatus( - const rfcomm_input* seeker) { - const uint8_t* in_use_key = seeker == NULL ? SelectInUseKey() : NULL; - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - rfcomm_input* input = &rfcomm_inputs[i]; - // Notify all seekers that are using the same key of the seeker - // if seeker is NULL, notify all seekers that are using the selected in - // use key - if (IsSassSeeker(input) && (IsSameAccountKey(input, seeker) || - UsesInUseAccountKey(input, in_use_key))) { - uint8_t buffer[MAX_NOTIFY_CONNECTION_STATUS_MESSAGE_SIZE]; - nearby_message_stream_Message reply; - reply.message_group = MESSAGE_GROUP_SASS; - reply.data = buffer; - reply.length = sizeof(buffer); - RETURN_IF_ERROR(PrepareNotifyConnectionStatus(&reply, input)); - nearby_message_stream_Send(input->state.peer_address, &reply); - } - } - return kNearbyStatusOK; -} - -// |seeker| is the peer that has initiated the update. -static void UpdateAndNotifySass(const rfcomm_input* seeker) { - if (advertisement_mode & NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE && - IncludeSass()) { - NEARBY_TRACE(INFO, "Audio state changed, update advertisement"); - nearby_platform_SetAdvertisement(NULL, 0, kDisabled); - SetNonDiscoverableAdvertisement(); - } - NotifySassConnectionStatus(seeker); -} -static void OnAudioStateChange() { UpdateAndNotifySass(NULL); } - -static char HexDigit(int digit) { - if (digit < 10) return '0' + digit; - if (digit < 16) return 'A' + digit - 10; - return '?'; -} - -static void OnMultipointSwitchEvent(uint8_t reason, uint64_t peer_address, - const char* name) { - uint8_t buffer[MAX_MESSAGE_STREAM_PAYLOAD_SIZE]; - nearby_message_stream_Message message; - message.message_group = MESSAGE_GROUP_SASS; - message.message_code = MESSAGE_CODE_SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT; - message.data = buffer; - message.data[0] = reason; - if (name != NULL) { - size_t name_length = strlen(name); - size_t max_name_length = - sizeof(buffer) - SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT_NAME_OFFSET; - if (name_length > max_name_length) name_length = max_name_length; - message.length = - SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT_NAME_OFFSET + name_length; - memcpy(message.data + SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT_NAME_OFFSET, name, - name_length); - } else { - message.length = 6; - message.data[2] = HexDigit((peer_address >> 12) & 0xF); - message.data[3] = HexDigit((peer_address >> 8) & 0xF); - message.data[4] = HexDigit((peer_address >> 4) & 0xF); - message.data[5] = HexDigit(peer_address & 0xF); - } - - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - rfcomm_input* input = &rfcomm_inputs[i]; - if (IsSassSeeker(input)) { - message.data[1] = - input->state.peer_address == peer_address - ? SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT_TARGET_THIS_DEVICE - : SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT_TARGET_ANOTHER_DEVICE; - nearby_message_stream_Send(input->state.peer_address, &message); - } - } -} - -static const nearby_platform_AudioCallbacks kAudioInterface = { - .on_state_change = OnAudioStateChange, - .on_multipoint_switch_event = OnMultipointSwitchEvent, -}; - -static void PrepareNotifySassCapabilityResponse( - nearby_message_stream_Message* message) { - NEARBY_ASSERT(message->length >= 2 * sizeof(uint16_t)); - message->message_code = MESSAGE_CODE_SASS_NOTIFY_CAPABILITY; - message->length = 2 * sizeof(uint16_t); - nearby_utils_CopyBigEndian(message->data, kSassVersion, sizeof(uint16_t)); - nearby_utils_CopyBigEndian(message->data + sizeof(uint16_t), - nearby_fp_GetSassCapabilityFlags(), - sizeof(uint16_t)); -} - -static void PrepareNotifySwitchingPreferenceResponse( - nearby_message_stream_Message* message) { - NEARBY_ASSERT(message->length >= 2); - message->message_code = MESSAGE_CODE_SASS_NOTIFY_SWITCHING_PREFERENCE; - message->length = 2; - message->data[0] = nearby_platform_GetSwitchingPreference(); - message->data[1] = 0; -} - -// Verifies MAC and sends a NACK if verification failed. -static nearby_platform_status VerifyMac( - uint64_t peer_address, const nearby_message_stream_Message* message, - rfcomm_input* input) { - nearby_platform_status status = nearby_fp_VerifyMessageAuthenticationCode( - message->data, message->length, input->in_use_account_key, - input->session_nonce); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(WARNING, "Invalid MAC on message %d", message->message_code); - nearby_message_stream_SendNack(peer_address, message, - FAIL_REASON_INVALID_MAC); - } - return status; -} - -// Finds the account key which was used to encode |message| and marks it at -// the in-use key for this session -static nearby_platform_status IndicateInUseKey( - const nearby_message_stream_Message* message, rfcomm_input* input) { - int offset = 0; - while (true) { - offset = nearby_fp_GetNextUniqueAccountKeyIndex(offset); - if (offset == -1) { - return kNearbyStatusInvalidInput; - } else if (kNearbyStatusOK == - nearby_fp_VerifyMessageAuthenticationCode( - message->data, message->length, - nearby_fp_GetAccountKey(offset)->account_key, - input->session_nonce)) { - memcpy(input->in_use_account_key, - nearby_fp_GetAccountKey(offset)->account_key, - ACCOUNT_KEY_SIZE_BYTES); - nearby_fp_MarkAccountKeyAsActive(offset); - UpdateAndNotifySass(NULL); - return kNearbyStatusOK; - } - offset++; - } -} - -// Selects a next, preferred audio source. The request to change the audio -// source came from |input|, which presumably is the current audio source. -static uint64_t FindNextAudioSource(const rfcomm_input* input) { - int i; - // 1. Select another seeker that uses the same account key. - for (i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - if (rfcomm_inputs[i].state.peer_address != INVALID_PEER_ADDRESS && - rfcomm_inputs[i].state.peer_address != input->state.peer_address && - IsSameAccountKey(&rfcomm_inputs[i], input)) { - return rfcomm_inputs[i].state.peer_address; - } - } - // 2. Select any other seeker. - for (i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - if (rfcomm_inputs[i].state.peer_address != INVALID_PEER_ADDRESS && - rfcomm_inputs[i].state.peer_address != input->state.peer_address) { - return rfcomm_inputs[i].state.peer_address; - } - } - // 3. There's only one connected seeker - return INVALID_PEER_ADDRESS; -} - -static nearby_platform_status HandleSassMessage( - uint64_t peer_address, nearby_message_stream_Message* message) { - rfcomm_input* input = GetRfcommInput(peer_address); - NEARBY_ASSERT(input != NULL); - uint8_t buffer[MAX_MESSAGE_STREAM_PAYLOAD_SIZE]; - nearby_message_stream_Message reply; - reply.message_group = MESSAGE_GROUP_SASS; - reply.data = buffer; - reply.length = sizeof(buffer); - switch (message->message_code) { - case MESSAGE_CODE_SASS_GET_CAPABILITY: - PrepareNotifySassCapabilityResponse(&reply); - return nearby_message_stream_Send(peer_address, &reply); - case MESSAGE_CODE_SASS_SET_MULTIPOINT_STATE: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 17)); - RETURN_IF_ERROR(VerifyMac(peer_address, message, input)); - bool enable = message->data[0] == 1; - NEARBY_TRACE(INFO, "Set Multipoint enable: %d", enable); - return SendResponse(peer_address, message, - nearby_platform_SetMultipoint(peer_address, enable)); - } - case MESSAGE_CODE_SASS_SET_SWITCHING_PREFERENCE: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 18)); - RETURN_IF_ERROR(VerifyMac(peer_address, message, input)); - uint8_t flags = message->data[0]; - NEARBY_TRACE(INFO, "Set switching preference: 0x%x", flags); - return SendResponse(peer_address, message, - nearby_platform_SetSwitchingPreference(flags)); - } - case MESSAGE_CODE_SASS_GET_SWITCHING_PREFERENCE: - PrepareNotifySwitchingPreferenceResponse(&reply); - return nearby_message_stream_Send(peer_address, &reply); - case MESSAGE_CODE_SASS_SWITCH_ACTIVE_AUDIO_SOURCE: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 17)); - RETURN_IF_ERROR(VerifyMac(peer_address, message, input)); - uint8_t flags = message->data[0]; - NEARBY_TRACE(INFO, "Switch active audio source: 0x%x", flags); - uint64_t preferred_audio_source = - ISSET(flags, 7) ? peer_address : FindNextAudioSource(input); - return SendResponse(peer_address, message, - nearby_platform_SwitchActiveAudioSource( - peer_address, flags, preferred_audio_source)); - } - case MESSAGE_CODE_SASS_SWITCH_BACK_AUDIO_SOURCE: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 17)); - RETURN_IF_ERROR(VerifyMac(peer_address, message, input)); - uint8_t flags = message->data[0]; - NEARBY_TRACE(INFO, "Switch back: 0x%x", flags); - return SendResponse( - peer_address, message, - nearby_platform_SwitchBackAudioSource(peer_address, flags)); - } - case MESSAGE_CODE_SASS_GET_CONNECTION_STATUS: - PrepareNotifyConnectionStatus(&reply, input); - return nearby_message_stream_Send(peer_address, &reply); - case MESSAGE_CODE_SASS_NOTIFY_SASS_INITIATED_CONNECTION: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 17)); - RETURN_IF_ERROR(VerifyMac(peer_address, message, input)); - uint8_t flags = message->data[0]; - NEARBY_TRACE(INFO, "Notify SASS initiated connection: 0x%x", flags); - return SendResponse( - peer_address, message, - nearby_platform_NotifySassInitiatedConnection(peer_address, flags)); - } - case MESSAGE_CODE_SASS_IN_USE_ACCOUNT_KEY: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 22)); - NEARBY_TRACE(INFO, "Indicate in-use key"); - return SendResponse(peer_address, message, - IndicateInUseKey(message, input)); - } - case MESSAGE_CODE_SASS_SEND_CUSTOM_DATA: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 17)); - RETURN_IF_ERROR(VerifyMac(peer_address, message, input)); - uint8_t data = message->data[0]; - NEARBY_TRACE(INFO, "Send custom data: 0x%x", data); - if (GetCustomData() != data) { - SetCustomData(data); - UpdateAndNotifySass(input); - } - return SendResponse(peer_address, message, kNearbyStatusOK); - } - case MESSAGE_CODE_SASS_SET_DROP_CONNECTION_TARGET: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 17)); - RETURN_IF_ERROR(VerifyMac(peer_address, message, input)); - uint8_t flags = message->data[0]; - NEARBY_TRACE(INFO, "Set drop connection target: 0x%x", flags); - return SendResponse( - peer_address, message, - nearby_platform_SetDropConnectionTarget(peer_address, flags)); - } - } - return kNearbyStatusOK; -} -#endif /* NEARBY_FP_ENABLE_SASS */ - -static void PrepareActiveComponentResponse( - nearby_message_stream_Message* message) { - NEARBY_ASSERT(message->length >= 2 * sizeof(uint16_t)); - message->message_code = MESSAGE_CODE_ACTIVE_COMPONENT_RESPONSE; - message->length = 1; - message->data[0] = nearby_platform_GetEarbudLeftStatus() << 1 | - nearby_platform_GetEarbudRightStatus(); -} - -static nearby_platform_status HandleGeneralMessage( - uint64_t peer_address, nearby_message_stream_Message* message) { - rfcomm_input* input = GetRfcommInput(peer_address); - NEARBY_ASSERT(input != NULL); - uint8_t buffer[MAX_MESSAGE_STREAM_PAYLOAD_SIZE]; - nearby_message_stream_Message reply; - reply.data = buffer; - reply.length = sizeof(buffer); - switch (message->message_group) { - case MESSAGE_GROUP_DEVICE_INFORMATION_EVENT: { - reply.message_group = MESSAGE_GROUP_DEVICE_INFORMATION_EVENT; - switch (message->message_code) { - case MESSAGE_CODE_ACTIVE_COMPONENT_REQUEST: { - PrepareActiveComponentResponse(&reply); - return nearby_message_stream_Send(peer_address, &reply); - } - case MESSAGE_CODE_CAPABILITIES: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 1)); - uint8_t flags = message->data[0]; - NEARBY_TRACE(INFO, "Set capabilities: 0x%x", flags); - input->capabilities = flags; - return kNearbyStatusOK; - } - case MESSAGE_CODE_PLATFORM_TYPE: { - RETURN_IF_ERROR(VerifyMessageLength(peer_address, message, 2)); - uint8_t type = message->data[0]; - uint8_t build = message->data[1]; - NEARBY_TRACE(INFO, "Set platform type: 0x%x:0x%x", type, build); - input->platform_type = type; - input->platform_build = build; - return kNearbyStatusOK; - } - } - break; - } - case MESSAGE_GROUP_DEVICE_ACTION_EVENT: { - reply.message_group = MESSAGE_GROUP_DEVICE_ACTION_EVENT; - switch (message->message_code) { - case MESSAGE_CODE_RING: { - if (message->length < 1 || message->length > 2) { - NEARBY_TRACE(WARNING, "Invalid message(%d) length %d", - message->message_code, message->length); - nearby_message_stream_SendNack(peer_address, message, - /* fail reason= */ 0); - return kNearbyStatusInvalidInput; - } - uint8_t command = message->data[0]; - uint16_t timeout = 0; - if (message->length > 1) timeout = message->data[1]; - NEARBY_TRACE(INFO, "Set ring device: 0x%x %d", command, timeout); - return SendResponse(peer_address, message, - nearby_platform_Ring(command, timeout * 10)); - } - } - break; - } - } - return kNearbyStatusOK; -} - -static void OnMessageReceived(uint64_t peer_address, - nearby_message_stream_Message* message) { - nearby_platform_status status; - status = HandleGeneralMessage(peer_address, message); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(WARNING, - "Processing stream message failed with %d Peer address: %s", - status, nearby_utils_MacToString(peer_address)); - return; - } - -#ifdef NEARBY_FP_ENABLE_SASS - if (message->message_group == MESSAGE_GROUP_SASS) { - nearby_platform_status status = HandleSassMessage(peer_address, message); - if (kNearbyStatusOK != status) { - NEARBY_TRACE(WARNING, "Processing SASS message failed with %d", status); - return; - } - } -#endif /* NEARBY_FP_ENABLE_SASS */ - if (client_callbacks != NULL && client_callbacks->on_event != NULL) { - nearby_event_MessageStreamReceived payload = { - .peer_address = peer_address, - .message_group = message->message_group, - .message_code = message->message_code, - .length = message->length, - .data = message->data}; - nearby_event_Event event = {.event_type = kNearbyEventMessageStreamReceived, - .payload = (uint8_t*)&payload}; - client_callbacks->on_event(&event); - } -} - -nearby_platform_status nearby_fp_client_SendMessage( - uint64_t peer_address, const nearby_message_stream_Message* message) { - return nearby_message_stream_Send(peer_address, message); -} - -nearby_platform_status nearby_fp_client_SendAck( - const nearby_event_MessageStreamReceived* message) { - nearby_message_stream_Message stream_message = { - .message_group = message->message_group, - .message_code = message->message_code, - }; - return nearby_message_stream_SendAck(message->peer_address, &stream_message); -} - -nearby_platform_status nearby_fp_client_SendNack( - const nearby_event_MessageStreamReceived* message, uint8_t fail_reason) { - nearby_message_stream_Message stream_message = { - .message_group = message->message_group, - .message_code = message->message_code, - }; - return nearby_message_stream_SendNack(message->peer_address, &stream_message, - fail_reason); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -static void OnBatteryChanged(void) { - nearby_platform_status status; - if (pairing_state != kPairingStateIdle && - pairing_state != kPairingStateWaitingForAccountKeyWrite && - pairing_state != kPairingStateWaitingForAdditionalData) { - NEARBY_TRACE(ERROR, "%s: device is in pairing process", __func__); - return; - } - - if (IncludeBatteryInfo() && - (advertisement_mode & NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE)) { - status = nearby_platform_SetAdvertisement(NULL, 0, kDisabled); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "Failed to update battery change, status: %d", - status); - return; - } - - status = SetNonDiscoverableAdvertisement(); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, "Failed to update battery change, status: %d", - status); - return; - } - } - -#if NEARBY_FP_MESSAGE_STREAM - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - rfcomm_input* input = &rfcomm_inputs[i]; - if (input->state.peer_address != INVALID_PEER_ADDRESS) { - status = SendBatteryInfoMessage(input->state.peer_address); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, - "Failed to send battery change, status: %d " - "Peer address: %s", - status, - nearby_utils_MacToString(input->state.peer_address)); - } - status = SendBatteryTimeMessage(input->state.peer_address); - if (status != kNearbyStatusOK) { - NEARBY_TRACE(ERROR, - "Failed to send battery change, status: %d " - "Peer address: %s", - status, - nearby_utils_MacToString(input->state.peer_address)); - } - } - } -#endif /* NEARBY_FP_MESSAGE_STREAM */ -} -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -static const nearby_platform_BleInterface kBleInterface = { - .on_gatt_write = OnGattWrite, - .on_gatt_read = OnGattRead, -}; - -static const nearby_platform_BtInterface kBtInterface = { - .on_pairing_request = OnPairingRequest, - .on_paired = OnPaired, - .on_pairing_failed = OnPairingFailed, -#if NEARBY_FP_MESSAGE_STREAM - .on_message_stream_connected = OnMessageStreamConnected, - .on_message_stream_disconnected = OnMessageStreamDisconnected, - .on_message_stream_received = OnMessageStreamReceived, -#endif /* NEARBY_FP_MESSAGE_STREAM */ -}; - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -static nearby_platform_BatteryInterface kBatteryInterface = { - .on_battery_changed = OnBatteryChanged, -}; -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -static nearby_platform_status EnterDisabledMode() { - nearby_platform_SetDefaultCapabilities(); - return nearby_platform_SetAdvertisement(NULL, 0, kDisabled); -} - -static nearby_platform_status EnterDiscoverableMode() { - size_t length; - uint8_t advertisement[DISCOVERABLE_ADV_SIZE_BYTES]; - if (pairing_state != kPairingStateIdle && - pairing_state != kPairingStateWaitingForAccountKeyWrite && - pairing_state != kPairingStateWaitingForAdditionalData) { - NEARBY_TRACE(ERROR, "%s: device is in pairing process", __func__); - return kNearbyStatusError; - } - length = nearby_fp_CreateDiscoverableAdvertisement(advertisement, - sizeof(advertisement)); - length += nearby_fp_AppendTxPower(advertisement + length, - sizeof(advertisement) - length, - nearby_platform_GetTxLevel()); - return nearby_platform_SetAdvertisement(advertisement, length, - kNoLargerThan100ms); -} - -static nearby_platform_status EnterNonDiscoverableMode() { - if (pairing_state != kPairingStateIdle && - pairing_state != kPairingStateWaitingForAccountKeyWrite && - pairing_state != kPairingStateWaitingForAdditionalData) { - NEARBY_TRACE(ERROR, "%s: device is in pairing process", __func__); - return kNearbyStatusError; - } - nearby_platform_SetDefaultCapabilities(); - return SetNonDiscoverableAdvertisement(); -} - -static bool ShouldRotateBleAddress(int mode) { - if (IsInPairingMode()) { - return false; - } - // We should rotate if advertisement mode changes to discoverable to prevent - // replay attacks. - return (mode & NEARBY_FP_ADVERTISEMENT_DISCOVERABLE) && - (!(advertisement_mode & NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); -} - -static uint32_t GetRotationDelayMs() { - uint32_t delay_ms = ADDRESS_ROTATION_PERIOD_MS; - // Rotation should happen every 1024 seconds on average. It is required that - // the precise point at which the beacon starts advertising the new - // identifier is randomized within the window. This logic should give us - // +/-200 seconds variability. - for (int i = 0; i < 5; i++) { - delay_ms += (50 << i) * (int8_t)nearby_platform_Rand(); - } - return delay_ms; -} - -static void MaybeRotateBleAddress(); - -static void CancelAddressRotationTimer() { - void* task = address_rotation_task; - address_rotation_task = NULL; - if (task != NULL) { - nearby_platform_CancelTimer(task); - } -} - -static void ScheduleAddressRotation() { - CancelAddressRotationTimer(); - address_rotation_task = - nearby_platform_StartTimer(MaybeRotateBleAddress, GetRotationDelayMs()); -} - -static nearby_platform_status UpdateAdvertisements() { - if (advertisement_mode == NEARBY_FP_ADVERTISEMENT_NONE) { - return EnterDisabledMode(); - } - if (advertisement_mode & NEARBY_FP_ADVERTISEMENT_DISCOVERABLE) { - return EnterDiscoverableMode(); - } - if (advertisement_mode & NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE) { - return EnterNonDiscoverableMode(); - } - return kNearbyStatusUnsupported; -} - -static void MaybeRotateBleAddress() { - ScheduleAddressRotation(); - if (IsInPairingMode()) { - return; - } - RotateBleAddress(); - UpdateAdvertisements(); -} - -static bool NeedsPeriodicAddressRotation() { - // FP spec says we should rotate BLE adress every ~15 minutes when - // advertising - return (advertisement_mode & (NEARBY_FP_ADVERTISEMENT_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE)) != 0; -} - -nearby_platform_status nearby_fp_client_SetAdvertisement(int mode) { - if (advertisement_mode == mode) { - return kNearbyStatusOK; - } - if (ShouldRotateBleAddress(mode)) { - CancelAddressRotationTimer(); - RotateBleAddress(); - } - advertisement_mode = mode; - if (NeedsPeriodicAddressRotation() && address_rotation_task == NULL) { - ScheduleAddressRotation(); - } - return UpdateAdvertisements(); -} - -#if NEARBY_FP_MESSAGE_STREAM -nearby_platform_status nearby_fp_client_GetSeekerInfo( - nearby_fp_client_SeekerInfo* seeker_info, size_t* seeker_info_length) { - int sl = *seeker_info_length; - int inx = 0; - *seeker_info_length = inx; - for (int i = 0; i < NEARBY_MAX_RFCOMM_CONNECTIONS; i++) { - if (rfcomm_inputs[i].state.peer_address != INVALID_PEER_ADDRESS) { - if (inx >= sl) return kNearbyStatusInvalidInput; - seeker_info[inx].peer_address = rfcomm_inputs[i].state.peer_address; - seeker_info[inx].capabilities = rfcomm_inputs[i].capabilities; - seeker_info[inx].platform_type = rfcomm_inputs[i].platform_type; - seeker_info[inx].platform_build = rfcomm_inputs[i].platform_build; - inx++; - *seeker_info_length = inx; - } - } - return kNearbyStatusOK; -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -nearby_platform_status nearby_fp_client_Init( - const nearby_fp_client_Callbacks* callbacks) { - nearby_platform_status status; - - client_callbacks = callbacks; - pairing_state = kPairingStateIdle; - pairing_failure_count = 0; -#if NEARBY_FP_MESSAGE_STREAM - memset(rfcomm_inputs, 0, sizeof(rfcomm_inputs)); -#endif /* NEARBY_FP_MESSAGE_STREAM */ - advertisement_mode = NEARBY_FP_ADVERTISEMENT_NONE; - address_rotation_task = NULL; - peer_public_address = 0; - DiscardPendingAccountKey(); - - status = nearby_platform_OsInit(); - if (status != kNearbyStatusOK) return status; - - status = nearby_platform_SecureElementInit(); - if (status != kNearbyStatusOK) return status; - - status = nearby_platform_BtInit(&kBtInterface); - if (status != kNearbyStatusOK) return status; - - status = nearby_platform_BleInit(&kBleInterface); - if (status != kNearbyStatusOK) return status; - - status = nearby_platform_PersistenceInit(); - if (status != kNearbyStatusOK) return status; - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION - status = nearby_platform_BatteryInit(&kBatteryInterface); - if (status != kNearbyStatusOK) return status; -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - - status = nearby_fp_LoadAccountKeys(); - if (status != kNearbyStatusOK) return status; - -#ifdef NEARBY_FP_ENABLE_SASS - SetCustomData(0); - status = nearby_platform_AudioInit(&kAudioInterface); - if (status != kNearbyStatusOK) return status; -#endif /* NEARBY_FP_ENABLE_SASS */ - - RotateBleAddress(); - - return status; -} diff --git a/embedded/client/source/nearby_fp_client.h b/embedded/client/source/nearby_fp_client.h deleted file mode 100644 index a51fd7b2..00000000 --- a/embedded/client/source/nearby_fp_client.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_FP_CLIENT_H -#define NEARBY_FP_CLIENT_H - -// clang-format off -#include "nearby_config.h" -// clang-format on - -#include "nearby.h" -#include "nearby_event.h" -#include "nearby_message_stream.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef struct { - // Optional event callback - void (*on_event)(nearby_event_Event* event); -} nearby_fp_client_Callbacks; - -// Seeker information structure -// Returns current information on a given seeker. -typedef struct { - uint64_t peer_address; // address of peer/seeker - uint8_t capabilities; // Capability bits - // Bit 0: Companion app is installed/not installed. - // Bit 1: Silence mode is supported/not supported. - uint8_t platform_type; // platform type code (Android = 0x01) - uint8_t platform_build; // Platform build number (Android Pie=0x1c) -} nearby_fp_client_SeekerInfo; - -// No advertisement, default state -#define NEARBY_FP_ADVERTISEMENT_NONE 0x00 -// The device is discoverable and can be paired with -#define NEARBY_FP_ADVERTISEMENT_DISCOVERABLE 0x01 -// The device is not discoverable -#define NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE 0x02 -// Ask the Seeker to show pairing UI indication. This flag can be combined with -// NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE -#define NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR 0x04 -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -// Include battery and charging info in the advertisement. This flag can be -// combined with NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE -#define NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO 0x08 -// Ask the Seeker to show Battery UI indication. This flag can be combined with -// NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO -#define NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR 0x10 -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ -#ifdef NEARBY_FP_ENABLE_SASS -// Include SASS advertisement. This flag can be -// combined with NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE -#define NEARBY_FP_ADVERTISEMENT_SASS 0x20 -#endif /* NEARBY_FP_ENABLE_SASS */ - -// Sets Fast Pair advertisement type -nearby_platform_status nearby_fp_client_SetAdvertisement(int mode); - -// Initalizes Fast Pair provider. The |callbacks| are optional - can be NULL. -nearby_platform_status nearby_fp_client_Init( - const nearby_fp_client_Callbacks* callbacks); - -#if NEARBY_FP_MESSAGE_STREAM -// Serializes and sends |message| over Message Stream -nearby_platform_status nearby_fp_client_SendMessage( - uint64_t peer_address, const nearby_message_stream_Message* message); - -// Sends out an ACK message for a received |message|. Note that not all messages -// require an ACK -nearby_platform_status nearby_fp_client_SendAck( - const nearby_event_MessageStreamReceived* message); - -// Sends out a NACK message for a received |message| with |fail_reason| reason. -nearby_platform_status nearby_fp_client_SendNack( - const nearby_event_MessageStreamReceived* message, uint8_t fail_reason); - -// Sends out a enable or disable silence mode, which stops audio from being -// routed to the provider. -nearby_platform_status nearby_fp_client_SetSilenceMode(uint64_t peer_address, - bool enable); - -// Sends log buffer full message to seeker, which passes it on to the companion -// app to manage log collection. -nearby_platform_status nearby_fp_client_SignalLogBufferFull( - uint64_t peer_address); - -// Gets information on currently connected seekers. -// An array of `SeekerInfo` structures is passed in, along with the length. -// On output, `seeker_info_length` is the actual number of structures read. -// Returns an error if input array is too small to hold information about -// all connected seekers. -nearby_platform_status nearby_fp_client_GetSeekerInfo( - nearby_fp_client_SeekerInfo* seeker_info, size_t* seeker_info_length); - -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_FP_CLIENT_H */ diff --git a/embedded/client/tests/gLinux/audio.cc b/embedded/client/tests/gLinux/audio.cc deleted file mode 100644 index 947d5a08..00000000 --- a/embedded/client/tests/gLinux/audio.cc +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 "fakes.h" -#include "nearby.h" -#include "nearby_fp_client.h" -#include "nearby_platform_audio.h" - -static const nearby_platform_AudioCallbacks* callbacks; - -static bool multipoint = false; -static uint8_t switching_preference_flags = 0; -static uint64_t switch_active_peer_address = 0; -static uint8_t switch_active_flags = 0; -static uint64_t switch_active_preferred_audio_source = 0; -static uint64_t switch_back_peer_address = 0; -static uint8_t switch_back_flags = 0; -static uint64_t notify_peer_address = 0; -static uint8_t notify_flags = 0; -static uint64_t drop_peer_address = 0; -static uint8_t drop_flags = 0; -static uint64_t active_peer_address = 0; - -bool nearby_platform_GetEarbudRightStatus() { return false; } - -bool nearby_platform_GetEarbudLeftStatus() { return false; } - -unsigned int nearby_platform_GetAudioConnectionState() { - return NEARBY_PLATFORM_CONNECTION_STATE_A2DP_WITH_AVRCP; -} - -bool nearby_platform_OnHead() { return true; } - -// Returns true if the device can accept another audio connection without -// dropping any of the existing connections. -bool nearby_platform_CanAcceptConnection() { return false; } - -// When the device is in focus mode, connection switching is not allowed -bool nearby_platform_InFocusMode() { return false; } - -// Returns true if the current connection is auto-recconnected, meaning it is -// not connected by the user. For multi-point connections, returns true if any -// of the existing connections is auto-reconnected. -bool nearby_platform_AutoReconnected() { return false; } - -// Sets a bit in the |bitmap| for every connected peer. The bit stays cleared -// for bonded but not connected peers. The order change is acceptable if it is -// unavoidable, e.g. when users factory reset the headset or when the bonded -// device count reaches the upper limit. -// |length| is the |bitmap| length on input in bytes and used space on output. -// For example, if there are 5 bonded devices, then |length| should be set to 1. -void nearby_platform_GetConnectionBitmap(uint8_t* bitmap, size_t* length) { - if (*length > 0) { - bitmap[0] = 0x09; - *length = 1; - } -} - -bool nearby_platform_IsSassOn() { return true; } - -bool nearby_platform_IsMultipointConfigurable() { return true; } - -bool nearby_platform_IsMultipointOn() { return multipoint; } - -bool nearby_platform_IsOnHeadDetectionSupported() { return true; } - -bool nearby_platform_IsOnHeadDetectionEnabled() { return false; } - -nearby_platform_status nearby_platform_SetMultipoint(uint64_t peer_address, - bool enable) { - multipoint = enable; - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_SetSwitchingPreference(uint8_t flags) { - switching_preference_flags = flags; - return kNearbyStatusOK; -} - -// Gets switching preference flags -uint8_t nearby_platform_GetSwitchingPreference() { - return switching_preference_flags; -} - -nearby_platform_status nearby_platform_SwitchActiveAudioSource( - uint64_t peer_address, uint8_t flags, uint64_t preferred_audio_source) { - switch_active_peer_address = peer_address; - switch_active_flags = flags; - switch_active_preferred_audio_source = preferred_audio_source; - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_SwitchBackAudioSource( - uint64_t peer_address, uint8_t flags) { - switch_back_peer_address = peer_address; - switch_back_flags = flags; - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_NotifySassInitiatedConnection( - uint64_t peer_address, uint8_t flags) { - notify_peer_address = peer_address; - notify_flags = flags; - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_SetDropConnectionTarget( - uint64_t peer_address, uint8_t flags) { - drop_peer_address = peer_address; - drop_flags = flags; - return kNearbyStatusOK; -} - -uint64_t nearby_platform_GetActiveAudioSource() { return active_peer_address; } - -void nearby_test_fakes_SetActiveAudioSource(uint64_t peer_address) { - active_peer_address = peer_address; -} - -// Initializes Audio module -nearby_platform_status nearby_platform_AudioInit( - const nearby_platform_AudioCallbacks* audio_interface) { - multipoint = false; - switching_preference_flags = 0; - switch_active_peer_address = 0; - switch_active_flags = 0; - switch_active_preferred_audio_source = 0; - switch_back_peer_address = 0; - switch_back_flags = 0; - notify_peer_address = 0; - notify_flags = 0; - drop_peer_address = 0; - drop_flags = 0; - - callbacks = audio_interface; - return kNearbyStatusOK; -} - -uint64_t nearby_test_fakes_GetSassSwitchActiveSourcePeerAddress() { - return switch_active_peer_address; -} - -uint8_t nearby_test_fakes_GetSassSwitchActiveSourceFlags() { - return switch_active_flags; -} - -uint64_t nearby_test_fakes_GetSassSwitchActiveSourcePreferredAudioSource() { - return switch_active_preferred_audio_source; -} - -uint64_t nearby_test_fakes_GetSassSwitchBackPeerAddress() { - return switch_back_peer_address; -} - -uint8_t nearby_test_fakes_GetSassSwitchBackFlags() { return switch_back_flags; } - -uint64_t nearby_test_fakes_GetSassNotifyInitiatedConnectionPeerAddress() { - return notify_peer_address; -} - -uint8_t nearby_test_fakes_GetSassNotifyInitiatedConnectionFlags() { - return notify_flags; -} - -uint64_t nearby_test_fakes_GetSassDropConnectionTargetPeerAddress() { - return drop_peer_address; -} - -uint8_t nearby_test_fakes_GetSassDropConnectionTargetFlags() { - return drop_flags; -} - -void nearby_test_fakes_SassMultipointSwitch(uint8_t reason, - uint64_t peer_address, - const char* name) { - callbacks->on_multipoint_switch_event(reason, peer_address, name); -} diff --git a/embedded/client/tests/gLinux/battery.cc b/embedded/client/tests/gLinux/battery.cc deleted file mode 100644 index 685c8cd9..00000000 --- a/embedded/client/tests/gLinux/battery.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 "fakes.h" -#include "nearby.h" -#include "nearby_platform_battery.h" - -constexpr nearby_platform_BatteryInfo kDefaultBatteryInfo = { - .is_charging = true, - .right_bud_battery_level = 80, - .left_bud_battery_level = 85, - .charging_case_battery_level = 90, - .remaining_time_minutes = 100}; -static nearby_platform_BatteryInfo test_battery_info = kDefaultBatteryInfo; -static nearby_platform_status get_battery_info_result = kNearbyStatusOK; - -static const nearby_platform_BatteryInterface* battery_interface; -nearby_platform_status nearby_platform_GetBatteryInfo( - nearby_platform_BatteryInfo* battery_info) { - (*battery_info) = test_battery_info; - return get_battery_info_result; -} - -void nearby_test_fakes_SetIsCharging(bool charging) { - test_battery_info.is_charging = charging; -} - -void nearby_test_fakes_SetRightBudBatteryLevel(unsigned battery_level) { - test_battery_info.right_bud_battery_level = battery_level; -} - -void nearby_test_fakes_SetLeftBudBatteryLevel(unsigned battery_level) { - test_battery_info.left_bud_battery_level = battery_level; -} - -void nearby_test_fakes_SetChargingCaseBatteryLevel(unsigned battery_level) { - test_battery_info.charging_case_battery_level = battery_level; -} - -void nearby_test_fakes_BatteryTime(uint16_t battery_time) { - test_battery_info.remaining_time_minutes = battery_time; -} - -void nearby_test_fakes_SetGetBatteryInfoResult(nearby_platform_status status) { - get_battery_info_result = status; -} - -nearby_platform_status nearby_platform_BatteryInit( - nearby_platform_BatteryInterface* callbacks) { - battery_interface = callbacks; - test_battery_info = kDefaultBatteryInfo; - get_battery_info_result = kNearbyStatusOK; - return kNearbyStatusOK; -} diff --git a/embedded/client/tests/gLinux/ble.cc b/embedded/client/tests/gLinux/ble.cc deleted file mode 100644 index 68e0eef6..00000000 --- a/embedded/client/tests/gLinux/ble.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 -#include - -// clang-format off -#include "nearby_config.h" -// clang-format on - -#include "fakes.h" -#include "nearby_platform_ble.h" -#include "nearby_platform_se.h" - -constexpr uint64_t kDefaultBleAddress = 0xbabababa; -static uint64_t ble_address = kDefaultBleAddress; -static uint64_t peer_address = 0x345678ab; -static const nearby_platform_BleInterface* ble_interface; -static std::map> notifications; -static std::vector advertisement; -static nearby_fp_AvertisementInterval interval; -constexpr int32_t kDefaultPsm = -1; -static int32_t psm = kDefaultPsm; - -std::map>& -nearby_test_fakes_GetGattNotifications() { - return notifications; -} - -// Gets BLE address. -uint64_t nearby_platform_GetBleAddress() { return ble_address; } - -// Sets BLE address. Returns address after change, which may be different than -// requested address. -uint64_t nearby_platform_SetBleAddress(uint64_t address) { - ble_address = address; - return ble_address; -} - -#ifdef NEARBY_FP_HAVE_BLE_ADDRESS_ROTATION -// Rotates BLE address to a random resolvable private address (RPA). Returns -// address after change. -uint64_t nearby_platform_RotateBleAddress() { - unsigned i; - uint64_t address = 0; - for (i = 0; i < sizeof(address); i++) { - address = (address << 8) ^ nearby_platform_Rand(); - } - address |= (uint64_t)1 << 46; - address &= ~((uint64_t)1 << 47); - nearby_platform_SetBleAddress(address); - return address; -} -#endif /* NEARBY_FP_HAVE_BLE_ADDRESS_ROTATION */ - -// Sends a notification to the connected GATT client. -nearby_platform_status nearby_platform_GattNotify( - uint64_t peer_address, nearby_fp_Characteristic characteristic, - const uint8_t* message, size_t length) { - notifications.emplace(characteristic, - std::vector(message, message + length)); - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_SetAdvertisement( - const uint8_t* payload, size_t length, - nearby_fp_AvertisementInterval interval) { - if (payload == NULL || length == 0) { - advertisement.clear(); - } else { - advertisement.assign(payload, payload + length); - } - ::interval = interval; - return kNearbyStatusOK; -} - -int32_t nearby_platform_GetMessageStreamPsm() { return psm; } - -// Initializes BLE -nearby_platform_status nearby_platform_BleInit( - const nearby_platform_BleInterface* callbacks) { - ble_interface = callbacks; - notifications.clear(); - advertisement.clear(); - interval = kDisabled; - ble_address = kDefaultBleAddress; - psm = kDefaultPsm; - return kNearbyStatusOK; -} - -void nearby_test_fakes_SetPsm(int32_t value) { psm = value; } - -std::vector& nearby_test_fakes_GetAdvertisement() { - return advertisement; -} - -nearby_platform_status nearby_test_fakes_GattReadModelId(uint8_t* output, - size_t* length) { - return ble_interface->on_gatt_read(peer_address, kModelId, output, length); -} - -nearby_platform_status nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - const uint8_t* request, size_t length) { - return ble_interface->on_gatt_write(peer_address, kKeyBasedPairing, request, - length); -} - -nearby_platform_status nearby_fp_fakes_ReceivePasskey(const uint8_t* request, - size_t length) { - return ble_interface->on_gatt_write(peer_address, kPasskey, request, length); -} - -nearby_platform_status nearby_fp_fakes_ReceiveAccountKeyWrite( - const uint8_t* request, size_t length) { - return ble_interface->on_gatt_write(peer_address, kAccountKey, request, - length); -} - -nearby_platform_status nearby_fp_fakes_ReceiveAdditionalData( - const uint8_t* request, size_t length) { - return ble_interface->on_gatt_write(peer_address, kAdditionalData, request, - length); -} - -nearby_platform_status nearby_fp_fakes_GattReadMessageStreamPsm( - uint8_t* output, size_t* length) { - return ble_interface->on_gatt_read(peer_address, kMessageStreamPsm, output, - length); -} diff --git a/embedded/client/tests/gLinux/bt.cc b/embedded/client/tests/gLinux/bt.cc deleted file mode 100644 index 96a14a75..00000000 --- a/embedded/client/tests/gLinux/bt.cc +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 -#include -#include - -#include "nearby_platform_bt.h" - -static const uint32_t kFastPairId = 0x101112; -static const int8_t kTxLevel = 33; -static const uint64_t kPublicAddress = 0xA0A1A2A3A4A5; -// No secondary identity address by default. -static const uint64_t kSecondaryPublicAddress = 0; -static const uint32_t kLocalPasskey = 123456; -static uint32_t remote_passkey; -static uint64_t remote_address; -static uint64_t paired_peer_address; -static std::map> rfcomm_outputs; -static std::vector device_name; -static bool pairing_mode = false; -static uint64_t secondary_public_address = kSecondaryPublicAddress; - -static const nearby_platform_BtInterface* bt_interface; -// Returns Fast Pair Model Id. -uint32_t nearby_platform_GetModelId() { return kFastPairId; } - -int8_t nearby_platform_GetTxLevel() { return kTxLevel; } - -// Returns public BR/EDR address -uint64_t nearby_platform_GetPublicAddress() { return kPublicAddress; } - -uint64_t nearby_platform_GetSecondaryPublicAddress() { - return secondary_public_address; -} - -// Returns passkey used during pairing -uint32_t nearby_platfrom_GetPairingPassKey() { return kLocalPasskey; } - -void nearby_platform_SetRemotePasskey(uint32_t passkey) { - remote_passkey = passkey; - if (remote_passkey == kLocalPasskey && - remote_address != 0 & bt_interface != NULL) { - paired_peer_address = remote_address; - bt_interface->on_paired(remote_address); - } -} - -nearby_platform_status nearby_platform_SendPairingRequest( - uint64_t remote_party_br_edr_address) { - remote_address = remote_party_br_edr_address; - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_SetFastPairCapabilities() { - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_SetDefaultCapabilities() { - remote_address = 0; - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_BtInit( - const nearby_platform_BtInterface* callbacks) { - bt_interface = callbacks; - remote_address = 0; - remote_passkey = 0; - paired_peer_address = 0; - pairing_mode = false; - secondary_public_address = kSecondaryPublicAddress; - rfcomm_outputs.clear(); - return kNearbyStatusOK; -} - -uint64_t nearby_test_fakes_GetPairingRequestAddress() { return remote_address; } - -uint32_t nearby_test_fakes_GetRemotePasskey() { return remote_passkey; } - -void nearby_test_fakes_SimulatePairing(uint64_t peer_address) { - remote_address = peer_address; - if (bt_interface != NULL) { - bt_interface->on_pairing_request(peer_address); - } -} - -void nearby_test_fakes_SetSecondaryPublicAddress(uint64_t address) { - secondary_public_address = address; -} - -uint64_t nearby_test_fakes_GetPairedDevice() { return paired_peer_address; } - -void nearby_test_fakes_DevicePaired(uint64_t peer_address) { - bt_interface->on_paired(peer_address); -} - -nearby_platform_status nearby_platform_SendMessageStream(uint64_t peer_address, - const uint8_t* message, - size_t length) { - rfcomm_outputs.emplace(peer_address, std::vector()); - auto rfcomm_output = rfcomm_outputs.find(peer_address); - for (int i = 0; i < length; i++) { - rfcomm_output->second.push_back(message[i]); - } - return kNearbyStatusOK; -} - -std::vector& nearby_test_fakes_GetRfcommOutput(uint64_t peer_address) { - return rfcomm_outputs[peer_address]; -} - -std::vector& nearby_test_fakes_GetRfcommOutput() { - return nearby_test_fakes_GetRfcommOutput(paired_peer_address); -} - -nearby_platform_status nearby_platform_SetDeviceName(const char* name) { - // + 1 for null terminator - device_name = std::vector(name, name + std::strlen(name) + 1); - return kNearbyStatusOK; -} - -// Gets null-terminated device name string in UTF-8 encoding -// pass buffer size in char, and get string length in char. -nearby_platform_status nearby_platform_GetDeviceName(char* name, - size_t* length) { - if (*length < device_name.size()) { - return kNearbyStatusResourceExhausted; - } - *length = device_name.size(); - std::memcpy(name, device_name.data(), device_name.size()); - return kNearbyStatusOK; -} - -bool nearby_platform_IsInPairingMode() { return pairing_mode; } - -void nearby_test_fakes_SetInPairingMode(bool in_pairing_mode) { - pairing_mode = in_pairing_mode; -} - -#if NEARBY_FP_MESSAGE_STREAM -void nearby_test_fakes_MessageStreamConnected(uint64_t peer_address) { - bt_interface->on_message_stream_connected(peer_address); -} - -void nearby_test_fakes_MessageStreamDisconnected(uint64_t peer_address) { - bt_interface->on_message_stream_disconnected(peer_address); -} - -void nearby_test_fakes_MessageStreamReceived(uint64_t peer_address, - const uint8_t* message, - size_t length) { - bt_interface->on_message_stream_received(peer_address, message, length); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ diff --git a/embedded/client/tests/gLinux/fakes.h b/embedded/client/tests/gLinux/fakes.h deleted file mode 100644 index 3d1a15b0..00000000 --- a/embedded/client/tests/gLinux/fakes.h +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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. - -// Copyright 2021 Google LLC. -#ifndef NEARBY_TEST_FAKES_H -#define NEARBY_TEST_FAKES_H -#include -#include -#include - -#include "nearby.h" -#include "nearby_platform_ble.h" - -void nearby_test_fakes_SetRandomNumber(unsigned int value); -void nearby_test_fakes_SetRandomNumberSequence(std::vector& value); - -std::vector nearby_test_fakes_GetRawAccountKeys(); - -nearby_platform_status nearby_test_fakes_GattReadModelId(uint8_t* output, - size_t* length); - -#ifdef MBEDTLS_FOR_SSL -extern "C" { -#endif -nearby_platform_status nearby_test_fakes_SetAntiSpoofingKey( - const uint8_t private_key[32], const uint8_t public_key[64]); -#ifdef MBEDTLS_FOR_SSL -} -#endif - -nearby_platform_status nearby_test_fakes_GenSec256r1Secret( - const uint8_t remote_party_public_key[64], uint8_t secret[32]); - -nearby_platform_status nearby_test_fakes_Aes128Decrypt( - const uint8_t input[AES_MESSAGE_SIZE_BYTES], - uint8_t output[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]); -nearby_platform_status nearby_test_fakes_Aes128Encrypt( - const uint8_t input[AES_MESSAGE_SIZE_BYTES], - uint8_t output[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]); - -std::vector& nearby_test_fakes_GetAdvertisement(); - -std::map>& -nearby_test_fakes_GetGattNotifications(); - -void nearby_test_fakes_SimulatePairing(uint64_t peer_address); -nearby_platform_status nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - const uint8_t* request, size_t length); -nearby_platform_status nearby_fp_fakes_ReceivePasskey(const uint8_t* request, - size_t length); -nearby_platform_status nearby_fp_fakes_ReceiveAccountKeyWrite( - const uint8_t* request, size_t length); -nearby_platform_status nearby_fp_fakes_ReceiveAdditionalData( - const uint8_t* request, size_t length); -nearby_platform_status nearby_fp_fakes_GattReadMessageStreamPsm(uint8_t* output, - size_t* length); -uint64_t nearby_test_fakes_GetPairingRequestAddress(); -uint32_t nearby_test_fakes_GetRemotePasskey(); -uint64_t nearby_test_fakes_GetPairedDevice(); -void nearby_test_fakes_DevicePaired(uint64_t peer_address); - -class AccountKeyPair { - public: - AccountKeyPair(uint64_t bt_address, const std::vector& account_key) - : address_(bt_address), account_key_(account_key) {} - AccountKeyPair(uint64_t bt_address, const uint8_t* account_key) - : address_(bt_address), - account_key_(account_key, account_key + ACCOUNT_KEY_SIZE_BYTES) {} - - uint64_t address_; - std::vector account_key_; -}; - -struct RawAccountKeyList { - uint8_t num_keys; - nearby_platform_AccountKeyInfo key[NEARBY_MAX_ACCOUNT_KEYS]; -}; - -class AccountKeyList { - public: - explicit AccountKeyList(const std::vector& raw_values) { - const RawAccountKeyList* list = - reinterpret_cast(raw_values.data()); - if (!list) return; - - for (size_t i = 0; i < list->num_keys; i++) { - uint64_t address = 0; -#ifdef NEARBY_FP_ENABLE_SASS - address = list->key[i].peer_address; -#endif /* NEARBY_FP_ENABLE_SASS */ - key_pairs_.emplace_back( - address, std::vector( - list->key[i].account_key, - list->key[i].account_key + ACCOUNT_KEY_SIZE_BYTES)); - } - } - explicit AccountKeyList(const std::vector& key_pairs) - : key_pairs_(key_pairs) {} - - size_t size() { return key_pairs_.size(); } - - std::vector GetKey(int index) { - return key_pairs_[index].account_key_; - } - - std::vector GetRawFormat() { - RawAccountKeyList account_keys; - account_keys.num_keys = size(); - for (size_t i = 0; i < size(); i++) { -#ifdef NEARBY_FP_ENABLE_SASS - account_keys.key[i].peer_address = key_pairs_[i].address_; -#endif /* NEARBY_FP_ENABLE_SASS */ - for (size_t j = 0; j < key_pairs_[i].account_key_.size(); j++) { - account_keys.key[i].account_key[j] = key_pairs_[i].account_key_[j]; - } - } - uint8_t* p = reinterpret_cast(&account_keys); - return std::vector(p, p + sizeof(account_keys)); - } - - private: - std::vector key_pairs_; -}; - -void nearby_test_fakes_SetAccountKeys(const uint8_t* input, size_t length); -void nearby_test_fakes_SetAccountKeys( - std::vector& account_key_pairs); -void nearby_test_fakes_SetAccountKeys(AccountKeyList& keys); - -AccountKeyList nearby_test_fakes_GetAccountKeys(); - -void nearby_test_fakes_SetIsCharging(bool charging); - -void nearby_test_fakes_SetRightBudBatteryLevel(unsigned battery_level); - -void nearby_test_fakes_SetLeftBudBatteryLevel(unsigned battery_level); - -void nearby_test_fakes_SetChargingCaseBatteryLevel(unsigned battery_level); - -void nearby_test_fakes_BatteryTime(uint16_t battery_time); - -void nearby_test_fakes_SetGetBatteryInfoResult(nearby_platform_status status); - -std::vector& nearby_test_fakes_GetRfcommOutput(); -std::vector& nearby_test_fakes_GetRfcommOutput(uint64_t peer_address); - -void nearby_test_fakes_MessageStreamConnected(uint64_t peer_address); - -void nearby_test_fakes_MessageStreamDisconnected(uint64_t peer_address); - -void nearby_test_fakes_MessageStreamReceived(uint64_t peer_address, - const uint8_t* message, - size_t length); - -uint32_t nearby_test_fakes_GetNextTimerMs(); -// Sets current time and triggers the timer callback if it expired -void nearby_test_fakes_SetCurrentTimeMs(uint32_t ms); - -void nearby_test_fakes_SetInPairingMode(bool in_pairing_mode); - -uint8_t nearby_test_fakes_GetRingCommand(void); - -uint16_t nearby_test_fakes_GetRingTimeout(void); -uint64_t nearby_test_fakes_GetSassSwitchActiveSourcePeerAddress(); -uint8_t nearby_test_fakes_GetSassSwitchActiveSourceFlags(); -uint64_t nearby_test_fakes_GetSassSwitchActiveSourcePreferredAudioSource(); -uint64_t nearby_test_fakes_GetSassSwitchBackPeerAddress(); -uint8_t nearby_test_fakes_GetSassSwitchBackFlags(); -uint64_t nearby_test_fakes_GetSassNotifyInitiatedConnectionPeerAddress(); -uint8_t nearby_test_fakes_GetSassNotifyInitiatedConnectionFlags(); -uint64_t nearby_test_fakes_GetSassDropConnectionTargetPeerAddress(); -uint8_t nearby_test_fakes_GetSassDropConnectionTargetFlags(); -void nearby_test_fakes_SassMultipointSwitch(uint8_t reason, - uint64_t peer_address, - const char* name); - -#ifdef NEARBY_FP_ENABLE_SASS -void nearby_test_fakes_SetActiveAudioSource(uint64_t peer_address); -#endif /* NEARBY_FP_ENABLE_SASS */ - -void nearby_test_fakes_SetPsm(int32_t value); - -void nearby_test_fakes_SetSecondaryPublicAddress(uint64_t address); - -#endif /* NEARBY_TEST_FAKES_H */ diff --git a/embedded/client/tests/gLinux/os.cc b/embedded/client/tests/gLinux/os.cc deleted file mode 100644 index 40d21899..00000000 --- a/embedded/client/tests/gLinux/os.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 - -#include "nearby_assert.h" -#include "nearby_platform_os.h" - -typedef void (*timer)(); -static timer timer_callback; -static uint32_t timer_trigger_time; -static bool timer_has_run; -static uint32_t current_time; -static constexpr nearby_platform_RingingInfo kDefaultRingingInfo = { - .ring_state = kRingStateStoppedReasonTimeout, - .num_components = 3, - .components = 0, - .timeout = 0, -}; - -static nearby_platform_RingingInfo ringing_info = kDefaultRingingInfo; - -// Gets current time in ms. -unsigned int nearby_platform_GetCurrentTimeMs() { return current_time; } - -// Starts a timer. Returns an opaque timer handle or null on error. -void* nearby_platform_StartTimer(void (*callback)(), unsigned int delay_ms) { - timer_callback = callback; - timer_trigger_time = nearby_platform_GetCurrentTimeMs() + delay_ms; - timer_has_run = false; - return (void*)timer_callback; -} - -// Cancels a timer -nearby_platform_status nearby_platform_CancelTimer(void* timer) { - NEARBY_ASSERT(timer == timer_callback); - timer_callback = NULL; - timer_trigger_time = 0; - return kNearbyStatusOK; -} - -uint32_t nearby_test_fakes_GetNextTimerMs() { return timer_trigger_time; } - -void nearby_test_fakes_SetCurrentTimeMs(uint32_t ms) { - current_time = ms; - if (!timer_has_run && timer_callback != NULL && timer_trigger_time <= ms) { - timer_has_run = true; - timer_callback(); - } -} - -nearby_platform_status nearby_platform_Ring(uint8_t command, uint16_t timeout) { - ringing_info.components = command; - ringing_info.timeout = timeout; - ringing_info.ring_state = kRingStateStarted; - return kNearbyStatusOK; -} - -uint8_t nearby_test_fakes_GetRingCommand(void) { - return ringing_info.components; -} - -uint16_t nearby_test_fakes_GetRingTimeout(void) { return ringing_info.timeout; } - -nearby_platform_status nearby_platform_OsInit() { - current_time = 0; - timer_callback = NULL; - timer_trigger_time = 0; - timer_has_run = false; - return kNearbyStatusOK; -} diff --git a/embedded/client/tests/gLinux/persistence.cc b/embedded/client/tests/gLinux/persistence.cc deleted file mode 100644 index 6dccc62c..00000000 --- a/embedded/client/tests/gLinux/persistence.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 -#include -#include - -#include "fakes.h" -#include "nearby_platform_persistence.h" - -static std::map> storage; -nearby_platform_status nearby_platform_LoadValue(nearby_fp_StoredKey key, - uint8_t* output, - size_t* length) { - auto search = storage.find(key); - if (search != storage.end()) { - size_t value_length = search->second.size(); - if (value_length > *length) { - *length = 0; - return kNearbyStatusResourceExhausted; - } - *length = value_length; - std::copy(search->second.begin(), search->second.end(), output); - } else { - // key not found. - *length = 0; - } - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_SaveValue(nearby_fp_StoredKey key, - const uint8_t* input, - size_t length) { - storage[key].assign(input, input + length); - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_PersistenceInit() { - storage.clear(); - return kNearbyStatusOK; -} - -void nearby_test_fakes_SetAccountKeys( - std::vector& account_key_pairs) { - AccountKeyList list(account_key_pairs); - nearby_test_fakes_SetAccountKeys(list); -} - -void nearby_test_fakes_SetAccountKeys(const uint8_t* input, size_t length) { - storage[kStoredKeyAccountKeyList].assign(input, input + length); -} - -std::vector nearby_test_fakes_GetRawAccountKeys() { - return storage[kStoredKeyAccountKeyList]; -} - -void nearby_test_fakes_SetAccountKeys(AccountKeyList& keys) { - auto v = keys.GetRawFormat(); - nearby_test_fakes_SetAccountKeys(v.data(), v.size()); -} - -AccountKeyList nearby_test_fakes_GetAccountKeys() { - return AccountKeyList(nearby_test_fakes_GetRawAccountKeys()); -} diff --git a/embedded/client/tests/gLinux/se.cc b/embedded/client/tests/gLinux/se.cc deleted file mode 100644 index a10d66b0..00000000 --- a/embedded/client/tests/gLinux/se.cc +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "fakes.h" -#include "nearby_platform_se.h" - -#pragma GCC diagnostic ignored "-Wunused-function" - -static unsigned int random_value = 0; -static std::queue random_sequence; - -static uint8_t private_key_store[32]; - -static std::unique_ptr anti_spoofing_key( - NULL, EVP_PKEY_free); - -static std::string ArrayToString(const uint8_t *data, size_t length) { - std::stringstream output; - output << "0x" << std::hex << std::setfill('0') << std::setw(2); - for (int i = 0; i < length; i++) { - output << (unsigned)data[i]; - } - return output.str(); -} - -// Generates a random number. -uint8_t nearby_platform_Rand() { - if (random_sequence.empty()) { - return random_value; - } else { - uint8_t v = random_sequence.front(); - random_sequence.pop(); - return v; - } -} - -#ifndef NEARBY_PLATFORM_USE_MBEDTLS -static SHA256_CTX sha256_context; - -nearby_platform_status nearby_platform_Sha256Start() { - SHA256_Init(&sha256_context); - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_Sha256Update(const void *data, - size_t length) { - SHA256_Update(&sha256_context, data, length); - return kNearbyStatusOK; -} - -nearby_platform_status nearby_platform_Sha256Finish(uint8_t out[32]) { - SHA256_Final(out, &sha256_context); - return kNearbyStatusOK; -} - -// Encrypts a data block with AES128 in ECB mode. -nearby_platform_status nearby_platform_Aes128Encrypt(const uint8_t input[16], - uint8_t output[16], - const uint8_t key[16]) { - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - int input_length = 16; - int output_length = 16; - - EVP_EncryptInit(ctx, EVP_aes_128_ecb(), key, NULL); - - if (1 != - EVP_EncryptUpdate(ctx, output, &output_length, input, input_length)) { - return kNearbyStatusError; - } - - EVP_CIPHER_CTX_free(ctx); - return kNearbyStatusOK; -} - -// Encrypts a data block with AES128 in ECB mode. -nearby_platform_status nearby_platform_Aes128Decrypt(const uint8_t input[16], - uint8_t output[16], - const uint8_t key[16]) { - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - int input_length = 16; - int output_length = 16; - - EVP_DecryptInit(ctx, EVP_aes_128_ecb(), key, NULL); - EVP_CIPHER_CTX_set_padding(ctx, 0); - - if (1 != - EVP_DecryptUpdate(ctx, output, &output_length, input, input_length)) { - return kNearbyStatusError; - } - - EVP_CIPHER_CTX_free(ctx); - return kNearbyStatusOK; -} -#endif /* NEARBY_PLATFORM_USE_MBEDTLS */ - -static EC_POINT *load_public_key(const uint8_t public_key[64]) { - BN_CTX *bn_ctx; - EC_KEY *key; - EC_POINT *point; - const EC_GROUP *group; - uint8_t oct_key[65]; - - oct_key[0] = 0x04; - memcpy(oct_key + 1, public_key, 64); - bn_ctx = BN_CTX_new(); - key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - group = EC_KEY_get0_group(key); - point = EC_POINT_new(group); - if (1 != EC_POINT_oct2point(group, point, oct_key, sizeof(oct_key), bn_ctx)) - return NULL; - BN_CTX_free(bn_ctx); - EC_KEY_free(key); - return point; -} - -static BIGNUM *load_private_key(const uint8_t private_key[32]) { - uint8_t buffer[37]; - buffer[0] = buffer[1] = buffer[2] = 0; - buffer[3] = 33; - buffer[4] = 0; - memcpy(buffer + 5, private_key, 32); - return BN_mpi2bn(buffer, sizeof(buffer), NULL); -} - -#ifdef NEARBY_PLATFORM_HAS_SE -// Generates a shared sec256p1 secret using remote party public key and this -// device's private key. -nearby_platform_status nearby_platform_GenSec256r1Secret( - const uint8_t remote_party_public_key[64], uint8_t secret[32]) { - EVP_PKEY_CTX *ctx; - EVP_PKEY *peerkey; - EC_POINT *peer_point; - EC_KEY *ec_peer_key; - size_t secret_len; - - /* Create the context for the shared secret derivation */ - if (NULL == (ctx = EVP_PKEY_CTX_new(anti_spoofing_key.get(), NULL))) - return kNearbyStatusError; - - /* Initialise */ - if (1 != EVP_PKEY_derive_init(ctx)) return kNearbyStatusError; - - if (NULL == (peer_point = load_public_key(remote_party_public_key))) - return kNearbyStatusError; - - ec_peer_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - - if (1 != EC_KEY_set_public_key(ec_peer_key, peer_point)) - return kNearbyStatusError; - - peerkey = EVP_PKEY_new(); - if (1 != EVP_PKEY_assign_EC_KEY(peerkey, ec_peer_key)) - return kNearbyStatusError; - - /* Provide the peer public key */ - if (1 != EVP_PKEY_derive_set_peer(ctx, peerkey)) return kNearbyStatusError; - - /* Determine buffer length for shared secret */ - if (1 != EVP_PKEY_derive(ctx, NULL, &secret_len)) return kNearbyStatusError; - - if (secret_len != 32) return kNearbyStatusError; - - /* Derive the shared secret */ - if (1 != (EVP_PKEY_derive(ctx, secret, &secret_len))) - return kNearbyStatusError; - - EVP_PKEY_CTX_free(ctx); - EC_POINT_free(peer_point); - EVP_PKEY_free(peerkey); - - return kNearbyStatusOK; -} -#endif /* NEARBY_PLATFORM_HAS_SE */ - -void nearby_test_fakes_SetRandomNumber(unsigned int value) { - random_value = value; -} - -void nearby_test_fakes_SetRandomNumberSequence(std::vector &value) { - for (auto &v : value) random_sequence.push(v); -} - -nearby_platform_status nearby_test_fakes_SetAntiSpoofingKey( - const uint8_t private_key[32], const uint8_t public_key[64]) { - EC_KEY *key; - BIGNUM *prv; - EC_POINT *pub; - - prv = load_private_key(private_key); - if (prv == NULL) return kNearbyStatusError; - pub = load_public_key(public_key); - if (pub == NULL) return kNearbyStatusError; - - key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - - if (1 != EC_KEY_set_private_key(key, prv)) return kNearbyStatusError; - if (1 != EC_KEY_set_public_key(key, pub)) return kNearbyStatusError; - - anti_spoofing_key.reset(EVP_PKEY_new()); - if (1 != EVP_PKEY_assign_EC_KEY(anti_spoofing_key.get(), key)) - return kNearbyStatusError; - - memcpy(private_key_store, private_key, 32); - - BN_free(prv); - EC_POINT_free(pub); - return kNearbyStatusOK; -} - -nearby_platform_status nearby_test_fakes_GenSec256r1Secret( - const uint8_t remote_party_public_key[64], uint8_t secret[32]) { - return nearby_platform_GenSec256r1Secret(remote_party_public_key, secret); -} - -nearby_platform_status nearby_test_fakes_Aes128Decrypt( - const uint8_t input[AES_MESSAGE_SIZE_BYTES], - uint8_t output[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]) { - return nearby_platform_Aes128Decrypt(input, output, key); -} - -nearby_platform_status nearby_test_fakes_Aes128Encrypt( - const uint8_t input[AES_MESSAGE_SIZE_BYTES], - uint8_t output[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]) { - return nearby_platform_Aes128Encrypt(input, output, key); -} - -const uint8_t *nearby_platform_GetAntiSpoofingPrivateKey() { - return private_key_store; -} - -// Initializes secure element module -nearby_platform_status nearby_platform_SecureElementInit() { - random_value = 0; - random_sequence = std::queue(); - return kNearbyStatusOK; -} diff --git a/embedded/client/tests/gLinux/trace.cc b/embedded/client/tests/gLinux/trace.cc deleted file mode 100644 index 2a56567f..00000000 --- a/embedded/client/tests/gLinux/trace.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 - -#include -#include -#include -#include - -#include "nearby_platform_trace.h" - -void nearby_platform_Trace(nearby_platform_TraceLevel level, - const char *filename, int lineno, const char *fmt, - ...) { - char buff[1024]; - va_list args; - va_start(args, fmt); - - vsnprintf(buff, sizeof(buff), fmt, args); - std::cout << filename << ":" << lineno << " " << buff << std::endl; - va_end(args); -} - -void nearby_platfrom_CrashOnAssert(const char *filename, int lineno, - const char *reason) { - fprintf(stderr, "ASSERT %s, %s:%d\n", reason, filename, lineno); - abort(); -} - -void nearby_platform_TraceInit(void) {} diff --git a/embedded/client/tests/message_stream_test.cc b/embedded/client/tests/message_stream_test.cc deleted file mode 100644 index 2ad26916..00000000 --- a/embedded/client/tests/message_stream_test.cc +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 -#include -#include - -#include "fakes.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "nearby.h" -#include "nearby_message_stream.h" - -#if NEARBY_FP_MESSAGE_STREAM -constexpr uint64_t kPeerAddress = 0x101112; -constexpr size_t kBufferSize = 64; -constexpr size_t kMaxPayloadSize = - kBufferSize - sizeof(nearby_message_stream_Metadata); -constexpr size_t kHeaderSize = 4; - -using ::testing::ElementsAreArray; - -class StreamMessage { - public: - explicit StreamMessage(nearby_message_stream_Message* message) - : StreamMessage(message->message_group, message->message_code, - std::vector(message->data, - message->data + message->length)) {} - StreamMessage(uint8_t group, uint8_t code) : group_(group), code_(code) {} - StreamMessage(uint8_t group, uint8_t code, std::vector data) - : group_(group), code_(code), data_(data) {} - - bool operator==(const StreamMessage& b) const { - return this->group_ == b.group_ && this->code_ == b.code_ && - this->data_ == b.data_; - } - - private: - unsigned int group_; - unsigned int code_; - std::vector data_; - friend std::ostream& operator<<(std::ostream& os, - const StreamMessage& message); -}; - -static std::string VecToString(std::vector data) { - std::stringstream output; - output << "0x" << std::hex; - for (int i = 0; i < data.size(); i++) { - output << std::setfill('0') << std::setw(2) << (unsigned)data[i]; - } - return output.str(); -} - -std::ostream& operator<<(std::ostream& os, const StreamMessage& message) { - os << std::hex; - os << "group: 0x" << std::setfill('0') << std::setw(2) << message.group_; - os << " code: 0x" << std::setfill('0') << std::setw(2) << message.code_; - os << std::dec << " length: " << message.data_.size(); - if (message.data_.size() > 0) { - os << " data: " << VecToString(message.data_); - } - return os; -} - -uint8_t buffer[kBufferSize]; - -void OnMessageReceived(uint64_t peer_address, - nearby_message_stream_Message* message); - -class MessageStreamTest : public ::testing::Test { - public: - void Read(const uint8_t* data, size_t length) { - nearby_message_stream_Read(&stream_state_, data, length); - } - - void ReadByteByByte(const uint8_t* data, size_t length) { - for (int i = 0; i < length; i++) { - nearby_message_stream_Read(&stream_state_, data + i, 1); - } - } - - void Send(const nearby_message_stream_Message* message) { - nearby_message_stream_Send(kPeerAddress, message); - } - - void SendAck(const nearby_message_stream_Message* message) { - nearby_message_stream_SendAck(kPeerAddress, message); - } - - void SendNack(const nearby_message_stream_Message* message, - uint8_t fail_reason) { - nearby_message_stream_SendNack(kPeerAddress, message, fail_reason); - } - - protected: - void SetUp() override; - - std::deque received_messages_; - - private: - void AddMessage(nearby_message_stream_Message* message) { - received_messages_.emplace_back(StreamMessage(message)); - } - // To allow access to |AddMessage| - friend void OnMessageReceived(uint64_t peer_address, - nearby_message_stream_Message* message); - - nearby_message_stream_State stream_state_ = { - .on_message_received = OnMessageReceived, - .peer_address = kPeerAddress, - .length = sizeof(buffer), - .buffer = buffer}; -}* test_fixture; - -void MessageStreamTest::SetUp() { - test_fixture = this; - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_message_stream_Init(&stream_state_); -} - -void OnMessageReceived(uint64_t peer_address, - nearby_message_stream_Message* message) { - EXPECT_EQ(kPeerAddress, peer_address); - test_fixture->AddMessage(message); -} - -TEST_F(MessageStreamTest, ReadWholeMessageWithNoData) { - uint8_t group = 120; - uint8_t code = 130; - uint8_t message[] = {group, code, 0, 0}; - - Read(message, sizeof(message)); - - ASSERT_EQ(1, received_messages_.size()); - ASSERT_EQ(StreamMessage(group, code), received_messages_[0]); -} - -TEST_F(MessageStreamTest, ReadMessageInChunksWithNoData) { - uint8_t group = 120; - uint8_t code = 130; - uint8_t message[] = {group, code, 0, 0}; - - ReadByteByByte(message, sizeof(message)); - - ASSERT_EQ(1, received_messages_.size()); - ASSERT_EQ(StreamMessage(group, code), received_messages_[0]); -} - -TEST_F(MessageStreamTest, ReadWholeMessageSmallPayload) { - uint8_t group = 120; - uint8_t code = 130; - uint8_t message[] = {group, code, 0, 1, 30}; - - Read(message, sizeof(message)); - - ASSERT_EQ(1, received_messages_.size()); - ASSERT_EQ(StreamMessage(group, code, - std::vector(message + kHeaderSize, - message + sizeof(message))), - received_messages_[0]); -} - -TEST_F(MessageStreamTest, ReadMessageInChunksSmallPayload) { - uint8_t group = 120; - uint8_t code = 130; - uint8_t message[] = {group, code, 0, 1, 30}; - - ReadByteByByte(message, sizeof(message)); - - ASSERT_EQ(1, received_messages_.size()); - ASSERT_EQ(StreamMessage(group, code, - std::vector(message + kHeaderSize, - message + sizeof(message))), - received_messages_[0]); -} - -TEST_F(MessageStreamTest, ReadWholeMessageMaximumPayloadSize) { - uint8_t group = 120; - uint8_t code = 130; - uint8_t message[kHeaderSize + kMaxPayloadSize]; - message[0] = group; - message[1] = code; - message[2] = kMaxPayloadSize >> 8; - message[3] = kMaxPayloadSize; - for (unsigned i = 0; i < kMaxPayloadSize; i++) { - message[kHeaderSize + i] = i; - } - - Read(message, sizeof(message)); - - ASSERT_EQ(1, received_messages_.size()); - ASSERT_EQ(StreamMessage(group, code, - std::vector(message + kHeaderSize, - message + sizeof(message))), - received_messages_[0]); -} - -TEST_F(MessageStreamTest, ReadWholeMessageTruncatedPayload) { - uint8_t group = 120; - uint8_t code = 130; - constexpr size_t kPayloadSize = 0x102; - uint8_t message[kHeaderSize + kPayloadSize]; - message[0] = group; - message[1] = code; - message[2] = 0x01; - message[3] = 0x02; - for (unsigned i = 0; i < kPayloadSize; i++) { - message[kHeaderSize + i] = i; - } - - Read(message, sizeof(message)); - - ASSERT_EQ(1, received_messages_.size()); - ASSERT_EQ(StreamMessage( - group, code, - std::vector(message + kHeaderSize, - message + kHeaderSize + kMaxPayloadSize)), - received_messages_[0]); -} - -TEST_F(MessageStreamTest, ReadMessageInChunksTruncatedPayload) { - uint8_t group = 120; - uint8_t code = 130; - constexpr size_t kPayloadSize = 0x102; - uint8_t message[kHeaderSize + kPayloadSize]; - message[0] = group; - message[1] = code; - message[2] = 0x01; - message[3] = 0x02; - for (unsigned i = 0; i < kPayloadSize; i++) { - message[kHeaderSize + i] = i; - } - - ReadByteByByte(message, sizeof(message)); - - ASSERT_EQ(1, received_messages_.size()); - ASSERT_EQ(StreamMessage( - group, code, - std::vector(message + kHeaderSize, - message + kHeaderSize + kMaxPayloadSize)), - received_messages_[0]); -} - -TEST_F(MessageStreamTest, ReadTwoMessages) { - uint8_t group = 120; - uint8_t code = 130; - uint8_t group2 = 121; - uint8_t code2 = 131; - uint8_t message[] = {group, code, 0, 1, 30, group2, code2, 0, 2, 31, 32}; - - Read(message, sizeof(message)); - - ASSERT_EQ(2, received_messages_.size()); - ASSERT_EQ(StreamMessage(group, code, - std::vector(message + 4, message + 5)), - received_messages_[0]); - ASSERT_EQ(StreamMessage(group2, code2, - std::vector(message + 9, message + 11)), - received_messages_[1]); -} - -TEST_F(MessageStreamTest, ReadTwoMessagesByteByByte) { - uint8_t group = 120; - uint8_t code = 130; - uint8_t group2 = 121; - uint8_t code2 = 131; - uint8_t message[] = {group, code, 0, 1, 30, group2, code2, 0, 2, 31, 32}; - - ReadByteByByte(message, sizeof(message)); - - ASSERT_EQ(2, received_messages_.size()); - ASSERT_EQ(StreamMessage(group, code, - std::vector(message + 4, message + 5)), - received_messages_[0]); - ASSERT_EQ(StreamMessage(group2, code2, - std::vector(message + 9, message + 11)), - received_messages_[1]); -} - -TEST_F(MessageStreamTest, SendMessageNoPayload) { - nearby_message_stream_Message message{ - .message_group = 10, - .message_code = 20, - .length = 0, - .data = nullptr, - }; - constexpr uint8_t kExpectedOutput[] = {10, 20, 0, 0}; - - Send(&message); - - ASSERT_THAT( - kExpectedOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST_F(MessageStreamTest, SendMessageWithPayload) { - uint8_t payload[] = {20, 21, 22, 23, 24}; - nearby_message_stream_Message message{ - .message_group = 10, - .message_code = 11, - .length = sizeof(payload), - .data = payload, - }; - constexpr uint8_t kExpectedOutput[] = {10, 11, 0, sizeof(payload), 20, 21, - 22, 23, 24}; - - Send(&message); - - ASSERT_THAT( - kExpectedOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST_F(MessageStreamTest, SendAck) { - nearby_message_stream_Message message{ - .message_group = 10, - .message_code = 20, - .length = 0, - .data = nullptr, - }; - constexpr uint8_t kExpectedOutput[] = {0xFF, 1, 0, 2, 10, 20}; - - SendAck(&message); - - ASSERT_THAT( - kExpectedOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST_F(MessageStreamTest, SendNack) { - nearby_message_stream_Message message{ - .message_group = 10, - .message_code = 20, - .length = 0, - .data = nullptr, - }; - constexpr uint8_t kFailReason = 0x88; - constexpr uint8_t kExpectedOutput[] = {0xFF, 2, 0, 3, kFailReason, 10, 20}; - - SendNack(&message, kFailReason); - - ASSERT_THAT( - kExpectedOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/embedded/client/tests/smoke_test.cc b/embedded/client/tests/smoke_test.cc deleted file mode 100644 index 7fccda72..00000000 --- a/embedded/client/tests/smoke_test.cc +++ /dev/null @@ -1,3698 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 -#include -#include -#include -#include -#include -#include - -#include "fakes.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "nearby.h" -#include "nearby_event.h" -#include "nearby_fp_client.h" -#include "nearby_fp_library.h" -#include "nearby_platform_audio.h" -#include "nearby_platform_ble.h" -#include "nearby_platform_persistence.h" -#include "nearby_utils.h" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-const-variable" - -constexpr uint8_t kBobPrivateKey[32] = { - 0x02, 0xB4, 0x37, 0xB0, 0xED, 0xD6, 0xBB, 0xD4, 0x29, 0x06, 0x4A, - 0x4E, 0x52, 0x9F, 0xCB, 0xF1, 0xC4, 0x8D, 0x0D, 0x62, 0x49, 0x24, - 0xD5, 0x92, 0x27, 0x4B, 0x7E, 0xD8, 0x11, 0x93, 0xD7, 0x63}; -constexpr uint8_t kBobPublicKey[64] = { - 0xF7, 0xD4, 0x96, 0xA6, 0x2E, 0xCA, 0x41, 0x63, 0x51, 0x54, 0x0A, - 0xA3, 0x43, 0xBC, 0x69, 0x0A, 0x61, 0x09, 0xF5, 0x51, 0x50, 0x06, - 0x66, 0xB8, 0x3B, 0x12, 0x51, 0xFB, 0x84, 0xFA, 0x28, 0x60, 0x79, - 0x5E, 0xBD, 0x63, 0xD3, 0xB8, 0x83, 0x6F, 0x44, 0xA9, 0xA3, 0xE2, - 0x8B, 0xB3, 0x40, 0x17, 0xE0, 0x15, 0xF5, 0x97, 0x93, 0x05, 0xD8, - 0x49, 0xFD, 0xF8, 0xDE, 0x10, 0x12, 0x3B, 0x61, 0xD2}; - -constexpr uint8_t kAlicePrivateKey[32] = { - 0xD7, 0x5E, 0x54, 0xC7, 0x7D, 0x76, 0x24, 0x89, 0xE5, 0x7C, 0xFA, - 0x92, 0x37, 0x43, 0xF1, 0x67, 0x77, 0xA4, 0x28, 0x3D, 0x99, 0x80, - 0x0B, 0xAC, 0x55, 0x58, 0x48, 0x38, 0x93, 0xE5, 0xB0, 0x6D}; -constexpr uint8_t kAlicePublicKey[64] = { - 0x36, 0xAC, 0x68, 0x2C, 0x50, 0x82, 0x15, 0x66, 0x8F, 0xBE, 0xFE, - 0x24, 0x7D, 0x01, 0xD5, 0xEB, 0x96, 0xE6, 0x31, 0x8E, 0x85, 0x5B, - 0x2D, 0x64, 0xB5, 0x19, 0x5D, 0x38, 0xEE, 0x7E, 0x37, 0xBE, 0x18, - 0x38, 0xC0, 0xB9, 0x48, 0xC3, 0xF7, 0x55, 0x20, 0xE0, 0x7E, 0x70, - 0xF0, 0x72, 0x91, 0x41, 0x9A, 0xCE, 0x2D, 0x28, 0x14, 0x3C, 0x5A, - 0xDB, 0x2D, 0xBD, 0x98, 0xEE, 0x3C, 0x8E, 0x4F, 0xBF}; - -constexpr uint8_t kExpectedSharedSecret[32] = { - 0x9D, 0xAD, 0xE4, 0xF8, 0x6A, 0xC3, 0x48, 0x8B, 0xBA, 0xC2, 0xAC, - 0x34, 0xB5, 0xFE, 0x68, 0xA0, 0xEE, 0x5A, 0x67, 0x06, 0xF5, 0x43, - 0xD9, 0x06, 0x1A, 0xD5, 0x78, 0x89, 0x49, 0x8A, 0xE6, 0xBA}; - -constexpr uint8_t kExpectedAesKey[16] = {0xB0, 0x7F, 0x1F, 0x17, 0xC2, 0x36, - 0xCB, 0xD3, 0x35, 0x23, 0xC5, 0x15, - 0xF3, 0x50, 0xAE, 0x57}; - -constexpr uint64_t kRemoteDevice = 0xB0B1B2B3B4B5; - -constexpr uint8_t kTxPower = 33; -constexpr uint8_t kSalt = 0xAB; -constexpr uint8_t kDiscoverableAdvertisement[] = { - 6, 0x16, 0x2C, 0xFE, 0x10, 0x11, 0x12, 2, 0x0A, kTxPower}; - -constexpr uint8_t kSeekerAccountKey[16] = {0x04, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34}; -constexpr uint8_t kSeekerAccountKey2[16] = {0x04, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64}; - -constexpr bool kRegularBloomFormat = false; -constexpr bool kSassBloomFormat = true; -constexpr uint8_t* kNoInUseKey = NULL; -using ::testing::ElementsAreArray; - -static std::string VecToString(std::vector data) { - std::stringstream output; - output << "0x" << std::hex; - for (int i = 0; i < data.size(); i++) { - output << std::setfill('0') << std::setw(2) << (unsigned)data[i]; - } - return output.str(); -} - -// static std::string VecToString(uint8_t* start, uint8_t* end) { -// return VecToString(std::vector(start, end)); -// } - -static void Set5AccountKeys() { - uint8_t account_key1[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - uint8_t account_key2[] = {0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, - 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88}; - uint8_t account_key3[] = {0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, - 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3}; - uint8_t account_key4[] = {0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, - 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4}; - uint8_t account_key5[] = {0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, - 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key1), - AccountKeyPair(kRemoteDevice, account_key2), - AccountKeyPair(kRemoteDevice, account_key3), - AccountKeyPair(kRemoteDevice, account_key4), - AccountKeyPair(kRemoteDevice, account_key5)}; - nearby_test_fakes_SetAccountKeys(account_keys); -} - -class Event { - public: - explicit Event(nearby_event_Type type) : type_(type) {} - explicit Event(const nearby_event_Event* event) : Event(event->event_type) {} - - nearby_event_Type GetType() const { return type_; } - - virtual bool operator==(const Event& b) const { return type_ == b.type_; } - - virtual ~Event() {} - - protected: - virtual std::string ToString() const { - std::stringstream output; - output << "Event type: " << type_; - return output.str(); - } - nearby_event_Type type_; - friend std::ostream& operator<<(std::ostream& os, const Event& event); -}; - -class MessageStreamConnectedEvent : public Event { - public: - explicit MessageStreamConnectedEvent(uint64_t peer_address) - : Event(kNearbyEventMessageStreamConnected), - peer_address_(peer_address) {} - explicit MessageStreamConnectedEvent( - const nearby_event_MessageStreamConnected* payload) - : Event(kNearbyEventMessageStreamConnected), - peer_address_(payload->peer_address) { - EXPECT_NE(nullptr, payload); - } - explicit MessageStreamConnectedEvent(const nearby_event_Event* event) - : MessageStreamConnectedEvent( - (const nearby_event_MessageStreamConnected*)event->payload) { - EXPECT_EQ(kNearbyEventMessageStreamConnected, type_); - } - - virtual bool operator==(const Event& b) const override { - if (type_ != b.GetType()) return false; - const MessageStreamConnectedEvent* event = - (const MessageStreamConnectedEvent*)&b; - return peer_address_ == event->peer_address_; - } - - std::string ToString() const override { - std::stringstream output; - output << "Event type: " << type_ << " peer_address: " << peer_address_; - return output.str(); - } - - private: - uint64_t peer_address_; -}; - -class MessageStreamDisconnectedEvent : public Event { - public: - explicit MessageStreamDisconnectedEvent(uint64_t peer_address) - : Event(kNearbyEventMessageStreamDisconnected), - peer_address_(peer_address) {} - explicit MessageStreamDisconnectedEvent( - const nearby_event_MessageStreamDisconnected* payload) - : Event(kNearbyEventMessageStreamDisconnected), - peer_address_(payload->peer_address) { - EXPECT_NE(nullptr, payload); - } - explicit MessageStreamDisconnectedEvent(const nearby_event_Event* event) - : MessageStreamDisconnectedEvent( - (const nearby_event_MessageStreamDisconnected*)event->payload) { - EXPECT_EQ(kNearbyEventMessageStreamDisconnected, type_); - } - - virtual bool operator==(const Event& b) const override { - if (type_ != b.GetType()) return false; - const MessageStreamDisconnectedEvent* event = - (const MessageStreamDisconnectedEvent*)&b; - return peer_address_ == event->peer_address_; - } - - std::string ToString() const override { - std::stringstream output; - output << "Event type: " << type_ << " peer_address: " << peer_address_; - return output.str(); - } - - private: - uint64_t peer_address_; -}; - -class MessageStreamReceivedEvent : public Event { - public: - explicit MessageStreamReceivedEvent( - const nearby_event_MessageStreamReceived* payload) - : Event(kNearbyEventMessageStreamReceived) { - EXPECT_NE(nullptr, payload); - - peer_address_ = payload->peer_address; - group_ = payload->message_group; - code_ = payload->message_code; - if (payload->length > 0) { - data_ = - std::vector(payload->data, payload->data + payload->length); - } - } - explicit MessageStreamReceivedEvent(const nearby_event_Event* event) - : MessageStreamReceivedEvent( - (const nearby_event_MessageStreamReceived*)event->payload) { - EXPECT_EQ(kNearbyEventMessageStreamReceived, event->event_type); - } - - virtual bool operator==(const Event& b) const override { - if (type_ != b.GetType()) return false; - const MessageStreamReceivedEvent* event = - (const MessageStreamReceivedEvent*)&b; - return peer_address_ == event->peer_address_ && group_ == event->group_ && - code_ == event->code_ && data_ == event->data_; - } - - std::string ToString() const override { - std::stringstream output; - output << "Event type: " << type_ << " peer_address: " << peer_address_ - << " group: " << (int)group_ << " code: " << (int)code_ - << " length: " << data_.size(); - if (data_.size() > 0) { - output << " data: " << VecToString(data_); - } - return output.str(); - } - - private: - uint64_t peer_address_; - uint8_t group_; - uint8_t code_; - std::vector data_; -}; - -std::ostream& operator<<(std::ostream& os, const Event& event) { - os << event.ToString(); - return os; -} - -static std::unique_ptr GetEvent(const nearby_event_Event* event) { - switch (event->event_type) { - case kNearbyEventMessageStreamConnected: - return std::make_unique(event); - case kNearbyEventMessageStreamDisconnected: - return std::make_unique(event); - case kNearbyEventMessageStreamReceived: - return std::make_unique(event); - } - return std::make_unique(event); -} - -std::vector> message_stream_events; -static void OnEventCallback(nearby_event_Event* event) { - message_stream_events.push_back(GetEvent(event)); -} - -constexpr nearby_fp_client_Callbacks kClientCallbacks = {.on_event = - OnEventCallback}; - -static void WriteToAccountKey() { - uint8_t encrypted_account_key_write_request[16]; - nearby_test_fakes_Aes128Encrypt( - kSeekerAccountKey, encrypted_account_key_write_request, kExpectedAesKey); - nearby_fp_fakes_ReceiveAccountKeyWrite( - encrypted_account_key_write_request, - sizeof(encrypted_account_key_write_request)); -} - -#if NEARBY_FP_MESSAGE_STREAM -int GetCapability(uint64_t peer_address) { - nearby_fp_client_SeekerInfo seeker_infos[NEARBY_MAX_RFCOMM_CONNECTIONS]; - size_t sl = NEARBY_MAX_RFCOMM_CONNECTIONS; - nearby_fp_client_GetSeekerInfo(seeker_infos, &sl); - - for (int i = 0; i < sl; i++) { - if (seeker_infos[i].peer_address == peer_address) { - return seeker_infos[i].capabilities; - } - } - return -1; -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -// |flags| from Table 1.2.1: Raw Request (type 0x00) in FP specification -static void Pair(uint8_t flags) { - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - nearby_test_fakes_SetRandomNumber(kSalt); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = flags; - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - // BT negotatiates passkey 123456 (0x01E240) - uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; - uint8_t encrypted_passkey_block[16]; - nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, - kExpectedAesKey); - // Seeker sends the passkey to provider - nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, - sizeof(encrypted_passkey_block)); - - // Seeker sends their account key - WriteToAccountKey(); -} - -TEST(NearbyFpClient, Init) { - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); -} - -TEST(NearbyFpClient, AccountKeyListIsEmpty) { - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(0, keys.size()); -} - -TEST(NearbyFpClient, CopyBigEndian_4bytes) { - uint8_t buffer[4]; - uint32_t value = 0x01020304; - - nearby_utils_CopyBigEndian(buffer, value, 4); - - ASSERT_EQ(1, buffer[0]); - ASSERT_EQ(2, buffer[1]); - ASSERT_EQ(3, buffer[2]); - ASSERT_EQ(4, buffer[3]); -} - -TEST(NearbyFpClient, CopyBigEndian_3bytes) { - uint8_t buffer[3]; - uint32_t value = 0x00010203; - - nearby_utils_CopyBigEndian(buffer, value, 3); - - ASSERT_EQ(1, buffer[0]); - ASSERT_EQ(2, buffer[1]); - ASSERT_EQ(3, buffer[2]); -} - -TEST(NearbyFpClient, AdvertisementDiscoverable) { - const int kBufferSize = DISCOVERABLE_ADV_SIZE_BYTES; - uint8_t buffer[kBufferSize]; - nearby_fp_client_Init(NULL); - - size_t written = - nearby_fp_CreateDiscoverableAdvertisement(buffer, kBufferSize); - written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, - kTxPower); - - ASSERT_EQ(kBufferSize, written); - ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), - ElementsAreArray(kDiscoverableAdvertisement)); -} - -TEST(NearbyFpClient, AdvertisementNondiscoverable_noKeys) { - const int kBufferSize = 9; - uint8_t buffer[kBufferSize]; - const uint8_t kExpectedResult[] = {5, 0x16, 0x2C, 0xFE, 0x00, - 0x00, 2, 0x0A, kTxPower}; - nearby_fp_client_Init(NULL); - - size_t written = - nearby_fp_CreateNondiscoverableAdvertisement(buffer, kBufferSize, false); - written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, - kTxPower); - - ASSERT_EQ(kBufferSize, written); - ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), - ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, AdvertisementNondiscoverable_oneKey) { - uint8_t salt = 0xC7; - uint8_t account_key[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key)}; - // Expected result for salt size 1 - const uint8_t kExpectedResult1[] = {11, 0x16, 0x2C, 0xFE, 0x00, - 0x42, 0x0A, 0x42, 0x88, 0x10, - 0x11, salt, 2, 0x0A, kTxPower}; - // Expected result for salt size 2 - const uint8_t kExpectedResult2[] = {12, 0x16, 0x2C, 0xFE, 0x00, 0x42, - 0x08, 0x48, 0x0c, 0x11, 0x21, salt, - salt, 2, 0x0A, kTxPower}; - const uint8_t* kExpectedResult = - (NEARBY_FP_SALT_SIZE == 1) ? kExpectedResult1 : kExpectedResult2; - const int kBufferSize = (NEARBY_FP_SALT_SIZE == 1) ? sizeof(kExpectedResult1) - : sizeof(kExpectedResult2); - uint8_t buffer[kBufferSize]; - - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAccountKeys(account_keys); - nearby_test_fakes_SetRandomNumber(salt); - nearby_fp_LoadAccountKeys(); - - size_t written = - nearby_fp_CreateNondiscoverableAdvertisement(buffer, kBufferSize, false); - nearby_fp_SetBloomFilter(buffer, kRegularBloomFormat, kNoInUseKey); - written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, - kTxPower); - - ASSERT_EQ(kBufferSize, written); - ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), - ElementsAreArray(kExpectedResult, kBufferSize)); -} - -#if (NEARBY_FP_SALT_SIZE == 2) -TEST(NearbyFpClient, AdvertisementNondiscoverable_oneKey_twoByteSalt) { - const int kBufferSize = 16; - uint8_t buffer[kBufferSize]; - std::vector salt = {0xC7, 0xC8}; - uint8_t account_key[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key)}; - const uint8_t kExpectedResult[] = { - 12, 0x16, 0x2C, 0xFE, 0x00, 0x42, 0x02, 0x0c, - 0x80, 0x2a, 0x21, salt[0], salt[1], 2, 0x0A, kTxPower}; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAccountKeys(account_keys); - nearby_test_fakes_SetRandomNumberSequence(salt); - nearby_fp_LoadAccountKeys(); - - size_t written = - nearby_fp_CreateNondiscoverableAdvertisement(buffer, kBufferSize, false); - nearby_fp_SetBloomFilter(buffer, kRegularBloomFormat, kNoInUseKey); - written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, - kTxPower); - - ASSERT_EQ(kBufferSize, written); - ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), - ElementsAreArray(kExpectedResult)); -} -#endif - -TEST(NearbyFpClient, AdvertisementNondiscoverable_twoKeys) { - uint8_t salt = 0xC7; - uint8_t account_key1[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - uint8_t account_key2[] = {0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, - 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key1), - AccountKeyPair(kRemoteDevice, account_key2)}; - const uint8_t kExpectedResult1[] = {12, 0x16, 0x2C, 0xFE, 0x00, 0x52, - 0x2f, 0xba, 0x06, 0x42, 0x00, 0x11, - salt, 2, 0x0A, kTxPower}; - const uint8_t kExpectedResult2[] = {13, 0x16, 0x2C, 0xFE, 0x00, 0x52, - 0x4d, 0x08, 0x00, 0x5d, 0x1c, 0x21, - salt, salt, 2, 0x0A, kTxPower}; - const uint8_t* kExpectedResult = - (NEARBY_FP_SALT_SIZE == 1) ? kExpectedResult1 : kExpectedResult2; - const int kBufferSize = (NEARBY_FP_SALT_SIZE == 1) ? sizeof(kExpectedResult1) - : sizeof(kExpectedResult2); - uint8_t buffer[kBufferSize]; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAccountKeys(account_keys); - nearby_test_fakes_SetRandomNumber(salt); - nearby_fp_LoadAccountKeys(); - - size_t written = - nearby_fp_CreateNondiscoverableAdvertisement(buffer, kBufferSize, false); - nearby_fp_SetBloomFilter(buffer, kRegularBloomFormat, kNoInUseKey); - written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, - kTxPower); - - ASSERT_EQ(kBufferSize, written); - ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), - ElementsAreArray(kExpectedResult, kBufferSize)); -} - -TEST(NearbyFpClient, - AdvertisementNondiscoverable_duplicateKeys_ignoreDuplicates) { - uint8_t salt = 0xC7; - constexpr uint64_t kOtherAddress = 0x505050505050; - uint8_t account_key1[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - uint8_t account_key2[] = {0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, - 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key1), - AccountKeyPair(kRemoteDevice, account_key2), - AccountKeyPair(kOtherAddress, account_key2), - AccountKeyPair(kOtherAddress, account_key1), - }; - const uint8_t kExpectedResult1[] = {12, 0x16, 0x2C, 0xFE, 0x00, 0x52, - 0x2F, 0xBA, 0x06, 0x42, 0x00, 0x11, - salt, 2, 0x0A, kTxPower}; - const uint8_t kExpectedResult2[] = {13, 0x16, 0x2C, 0xFE, 0x00, 0x52, - 0x4D, 0x08, 0x00, 0x5D, 0x1C, 0x21, - salt, salt, 2, 0x0A, kTxPower}; - const uint8_t* kExpectedResult = - (NEARBY_FP_SALT_SIZE == 1) ? kExpectedResult1 : kExpectedResult2; - const int kBufferSize = (NEARBY_FP_SALT_SIZE == 1) ? sizeof(kExpectedResult1) - : sizeof(kExpectedResult2); - uint8_t buffer[kBufferSize]; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAccountKeys(account_keys); - nearby_test_fakes_SetRandomNumber(salt); - nearby_fp_LoadAccountKeys(); - - size_t written = - nearby_fp_CreateNondiscoverableAdvertisement(buffer, kBufferSize, false); - nearby_fp_SetBloomFilter(buffer, kRegularBloomFormat, kNoInUseKey); - written += nearby_fp_AppendTxPower(buffer + written, kBufferSize - written, - kTxPower); - - ASSERT_EQ(kBufferSize, written); - std::cout << "Buffer: " - << VecToString(std::vector(buffer, buffer + kBufferSize)) - << std::endl; - ASSERT_THAT(std::vector(buffer, buffer + kBufferSize), - ElementsAreArray(kExpectedResult, kBufferSize)); -} - -TEST(NearbyFpClient, GattReadModelId) { - uint8_t buffer[3]; - size_t length = sizeof(buffer); - nearby_fp_client_Init(NULL); - - ASSERT_EQ(kNearbyStatusOK, - nearby_test_fakes_GattReadModelId(buffer, &length)); - - ASSERT_EQ(sizeof(buffer), length); - ASSERT_EQ(0x10, buffer[0]); - ASSERT_EQ(0x11, buffer[1]); - ASSERT_EQ(0x12, buffer[2]); -} - -TEST(NearbyFpClient, SetAntiSpoofingKey) { - nearby_fp_client_Init(NULL); - - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); -} - -TEST(NearbyFpClient, GenSec256r1Secret_bobAlice) { - uint8_t secret[32]; - nearby_fp_client_Init(NULL); - - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - ASSERT_EQ(kNearbyStatusOK, - nearby_test_fakes_GenSec256r1Secret(kAlicePublicKey, secret)); - - for (int i = 0; i < sizeof(secret); i++) { - ASSERT_EQ(kExpectedSharedSecret[i], secret[i]) - << "Difference at position: " << i; - } -} - -TEST(NearbyFpClient, GenSec256r1Secret_aliceBob) { - uint8_t secret[32]; - nearby_fp_client_Init(NULL); - - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kAlicePrivateKey, kAlicePublicKey)); - ASSERT_EQ(kNearbyStatusOK, - nearby_test_fakes_GenSec256r1Secret(kBobPublicKey, secret)); - - for (int i = 0; i < sizeof(secret); i++) { - ASSERT_EQ(kExpectedSharedSecret[i], secret[i]) - << "Difference at position: " << i; - } -} - -TEST(NearbyFpClient, CreateSharedSecret_aliceBob) { - uint8_t secret[16]; - nearby_fp_client_Init(NULL); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kAlicePrivateKey, kAlicePublicKey)); - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_CreateSharedSecret(kBobPublicKey, secret)); - - for (int i = 0; i < sizeof(secret); i++) { - ASSERT_EQ(kExpectedAesKey[i], secret[i]) << "Difference at position: " << i; - } -} - -TEST(NearbyFpClient, CreateSharedSecret_bobAlice) { - uint8_t secret[16]; - nearby_fp_client_Init(NULL); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_CreateSharedSecret(kAlicePublicKey, secret)); - - for (int i = 0; i < sizeof(secret); i++) { - ASSERT_EQ(kExpectedAesKey[i], secret[i]) << "Difference at position: " << i; - } -} - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -TEST(NearbyFpClient, - SetAdvertisementWithBatteryNotification_AdvertisementWithPairingUI) { - // When the salt size is 2, the salt byte is repeated twice in this test. - uint8_t salt = 0xC7; - // Expected result with salt size 1 - const uint8_t kExpectedResult1[] = { - 0x10, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x03, 0x78, 0x95, 0x67, - 0x0c, 0xc3, 0x0a, 0xcc, 0x56, 0x11, salt, 0x02, 0x0a, kTxPower}; - // Expected result with salt size 2 - const uint8_t kExpectedResult2[] = { - 0x11, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x04, 0xac, 0x49, 0x24, 0x23, - 0x4b, 0xd1, 0x6d, 0x9f, 0x21, salt, salt, 0x02, 0x0a, kTxPower}; - const uint8_t* kExpectedResult = - (NEARBY_FP_SALT_SIZE == 1) ? kExpectedResult1 : kExpectedResult2; - const int kBufferSize = (NEARBY_FP_SALT_SIZE == 1) ? sizeof(kExpectedResult1) - : sizeof(kExpectedResult2); - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - Set5AccountKeys(); - nearby_test_fakes_SetRandomNumber(salt); - nearby_fp_LoadAccountKeys(); - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR)); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kExpectedResult, kBufferSize)); -} - -TEST( - NearbyFpClient, - SetAdvertisementWithBatteryNotification_AdvertisementNoPairingUIWithBatteryUI) { - uint8_t salt = 0xC7; - const uint8_t kExpectedResult1[] = {0x14, 0x16, 0x2c, 0xfe, 0x00, 0x92, - 0x30, 0xa6, 0x17, 0x10, 0x0c, 0x6c, - 0xa9, 0xea, 0xf7, 0x11, salt, 0x33, - 0xd5, 0xd0, 0xda, 2, 0x0a, kTxPower}; - const uint8_t kExpectedResult2[] = { - 0x15, 0x16, 0x2c, 0xfe, 0x00, 0x92, 0x9c, 0x84, 0x20, - 0x0b, 0xb1, 0xd7, 0x37, 0x42, 0x93, 0x21, salt, salt, - 0x33, 0xd5, 0xd0, 0xda, 2, 0x0a, kTxPower}; - const uint8_t* kExpectedResult = - (NEARBY_FP_SALT_SIZE == 1) ? kExpectedResult1 : kExpectedResult2; - const int kBufferSize = (NEARBY_FP_SALT_SIZE == 1) ? sizeof(kExpectedResult1) - : sizeof(kExpectedResult2); - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - Set5AccountKeys(); - nearby_test_fakes_SetRandomNumber(salt); - nearby_fp_LoadAccountKeys(); - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR | - NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO)); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kExpectedResult, kBufferSize)); -} - -TEST( - NearbyFpClient, - SetAdvertisementWithBatteryNotification_Charging_AdvertisementContainsBatteryInfo) { - uint8_t salt = 0xC7; - const uint8_t kExpectedResult1[] = {0x14, 0x16, 0x2c, 0xfe, 0x00, 0x90, - 0x30, 0xa6, 0x17, 0x10, 0x0c, 0x6c, - 0xa9, 0xea, 0xf7, 0x11, salt, 0x33, - 0xd5, 0xd0, 0xda, 2, 0x0a, kTxPower}; - const uint8_t kExpectedResult2[] = { - 0x15, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x9c, 0x84, 0x20, - 0x0b, 0xb1, 0xd7, 0x37, 0x42, 0x93, 0x21, salt, salt, - 0x33, 0xd5, 0xd0, 0xda, 2, 0x0a, kTxPower}; - const uint8_t* kExpectedResult = - (NEARBY_FP_SALT_SIZE == 1) ? kExpectedResult1 : kExpectedResult2; - const int kBufferSize = (NEARBY_FP_SALT_SIZE == 1) ? sizeof(kExpectedResult1) - : sizeof(kExpectedResult2); - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - Set5AccountKeys(); - nearby_test_fakes_SetRandomNumber(salt); - nearby_fp_LoadAccountKeys(); - nearby_test_fakes_SetIsCharging(true); - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR | - NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR | - NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO)); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kExpectedResult, kBufferSize)); -} - -TEST( - NearbyFpClient, - SetAdvertisementWithBatteryNotification_NotCharging_AdvertisementContainsBatteryInfo) { - uint8_t salt = 0xC7; - const uint8_t kExpectedResult1[] = {0x14, 0x16, 0x2c, 0xfe, 0x00, 0x90, - 0x46, 0x84, 0x1e, 0x84, 0x2e, 0x27, - 0x05, 0x92, 0xcc, 0x11, salt, 0x33, - 0x55, 0x50, 0x5a, 2, 0x0a, kTxPower}; - const uint8_t kExpectedResult2[] = { - 0x15, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x59, 0x0d, 0x74, - 0xb3, 0xa3, 0x54, 0xe9, 0x28, 0x00, 0x21, salt, salt, - 0x33, 0x55, 0x50, 0x5a, 2, 0x0a, kTxPower}; - const uint8_t* kExpectedResult = - (NEARBY_FP_SALT_SIZE == 1) ? kExpectedResult1 : kExpectedResult2; - const int kBufferSize = (NEARBY_FP_SALT_SIZE == 1) ? sizeof(kExpectedResult1) - : sizeof(kExpectedResult2); - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - Set5AccountKeys(); - nearby_test_fakes_SetRandomNumber(salt); - nearby_fp_LoadAccountKeys(); - nearby_test_fakes_SetIsCharging(false); - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR | - NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR | - NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO)); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kExpectedResult, kBufferSize)); -} - -TEST( - NearbyFpClient, - SetAdvertisementWithBatteryNotification_GetBatteryInfoFails_AdvertismentIsValid) { - uint8_t salt = 0xC7; - const uint8_t kExpectedResult1[] = { - 0x10, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x03, 0x78, 0x95, 0x67, - 0x0c, 0xc3, 0x0a, 0xcc, 0x56, 0x11, salt, 2, 0x0a, kTxPower}; - const uint8_t kExpectedResult2[] = { - 0x11, 0x16, 0x2c, 0xfe, 0x00, 0x90, 0x04, 0xac, 0x49, 0x24, 0x23, - 0x4b, 0xd1, 0x6d, 0x9f, 0x21, salt, salt, 2, 0x0a, kTxPower}; - const uint8_t* kExpectedResult = - (NEARBY_FP_SALT_SIZE == 1) ? kExpectedResult1 : kExpectedResult2; - const int kBufferSize = (NEARBY_FP_SALT_SIZE == 1) ? sizeof(kExpectedResult1) - : sizeof(kExpectedResult2); - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - Set5AccountKeys(); - nearby_test_fakes_SetRandomNumber(salt); - nearby_fp_LoadAccountKeys(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR | - NEARBY_FP_ADVERTISEMENT_BATTERY_UI_INDICATOR | - NEARBY_FP_ADVERTISEMENT_INCLUDE_BATTERY_INFO)); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kExpectedResult, kBufferSize)); -} - -#if NEARBY_FP_MESSAGE_STREAM -TEST(NearbyFpClient, - RfcommConnected_HasBatteryInfo_SendsModelIdBleAddressAndBatteryInfo) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Battery level - 3, 3, 0, 3, 0xd5, 0xd0, 0xda, - // Battery remaining time - 3, 4, 0, 1, 100}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_BatteryTime(100); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_SetIsCharging(true); - - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - ASSERT_EQ(1, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, EnableSilenceMode_RfcommConnected) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Battery level - 3, 3, 0, 3, 0xd5, 0xd0, 0xda, - // Battery remaining time - 3, 4, 0, 1, 100, - // Enable silence mode - 1, 1, 0, 0}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_BatteryTime(100); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_fp_client_SetSilenceMode(kPeerAddress, true); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, DisableSilenceMode_RfcommConnected) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Battery level - 3, 3, 0, 3, 0xd5, 0xd0, 0xda, - // Battery remaining time - 3, 4, 0, 1, 100, - // Disable silence mode - 1, 2, 0, 0}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_BatteryTime(100); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_fp_client_SetSilenceMode(kPeerAddress, false); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, BatteryLevelLongForm_RfcommConnected) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Battery level - 3, 3, 0, 3, 0xd5, 0xd0, 0xda, - // Battery remaining time (256) - 3, 4, 0, 2, 1, 0, - // Disable silence mode - 1, 2, 0, 0}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_BatteryTime(0x100); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_fp_client_SetSilenceMode(kPeerAddress, false); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -#if NEARBY_FP_MESSAGE_STREAM -TEST(NearbyFpClient, EnableSilenceMode_NoRfcommConnection_ReturnsError) { - constexpr uint64_t kPeerAddress = 0x123456; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - - ASSERT_EQ(kNearbyStatusError, - nearby_fp_client_SetSilenceMode(kPeerAddress, true)); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -#if NEARBY_FP_MESSAGE_STREAM -TEST(NearbyFpClient, SignalLogBufferFull_RfcommConnected) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Battery level - 3, 3, 0, 3, 0xd5, 0xd0, 0xda, - // Battery remaining time - 3, 4, 0, 1, 100, - // Signal log buffer full - 2, 1, 0, 0}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_BatteryTime(100); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_fp_client_SignalLogBufferFull(kPeerAddress); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, - ReceiveActiveComponentsRequest_SendsActiveComponentResponse) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {// active components request - 3, 5, 0, 0}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = NULL}; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Battery level - 3, 3, 0, 3, 0xd5, 0xd0, 0xda, - // Battery remaining time - 3, 4, 0, 1, 100, - // Active component response - 3, 6, 0, 1, 0x00}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_BatteryTime(100); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -#if NEARBY_FP_MESSAGE_STREAM -TEST(NearbyFpClient, ReceiveCapabilities) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kCapabilities = 0x11; - constexpr uint8_t kPeerMessage[] = {// Seeker capabilities request, - // Companion app, silence mode. - 3, 7, 0, 1, kCapabilities}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); - ASSERT_EQ(kCapabilities, GetCapability(kPeerAddress)); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -#if NEARBY_FP_MESSAGE_STREAM -TEST(NearbyFpClient, ReceivePlatformType) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {// platform type request, - // Android, Pie SDK - 3, 8, 0, 2, 0x01, 0x1c}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -#if NEARBY_FP_MESSAGE_STREAM -TEST(NearbyFpClient, ReceiveRingRequest) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kRingTimeSeconds = 100; - constexpr uint16_t kRingTimeDeciseconds = 10 * kRingTimeSeconds; - constexpr uint8_t kPeerMessage[] = { - // Ring request, both buds, - // 100 seconds. - 4, - 1, - 0, - 2, - MESSAGE_CODE_RING_LEFT | MESSAGE_CODE_RING_RIGHT, - kRingTimeSeconds}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); - ASSERT_EQ(nearby_test_fakes_GetRingCommand(), - MESSAGE_CODE_RING_LEFT | MESSAGE_CODE_RING_RIGHT); - ASSERT_EQ(nearby_test_fakes_GetRingTimeout(), kRingTimeDeciseconds); -} -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -TEST(NearbyFpClient, Pairing_ProviderInitiated) { - uint8_t salt = 0xAB; - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); - nearby_test_fakes_SetRandomNumber(salt); - - // Provider sets the advertisement - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kDiscoverableAdvertisement)); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = 0x40; // bit 1 (msb) set - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); - std::cout << VecToString(response) << std::endl; - uint8_t decrypted_response[16]; - uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, - 0xA5, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - // Provider sends pairing request - ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairingRequestAddress()); - - // BT negotatiates passkey 123456 (0x01E240) - uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; - uint8_t encrypted_passkey_block[16]; - nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, - kExpectedAesKey); - // Seeker sends the passkey to provider - nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, - sizeof(encrypted_passkey_block)); - - // Provider sends the passkey to seeker - response = nearby_test_fakes_GetGattNotifications().at(kPasskey); - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, - salt, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); - ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); - - // Seeker sends their account key - WriteToAccountKey(); - - std::cout << "Account keys: " - << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); -} - -// Pairing flow where the Seeker writes to the account key a little bit too -// early - while the BT bonding is still in progress -TEST(NearbyFpClient, Pairing_WriteKeyBeforePaired_PairingSuccessful) { - uint8_t salt = 0xAB; - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); - nearby_test_fakes_SetRandomNumber(salt); - - // Provider sets the advertisement - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kDiscoverableAdvertisement)); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = 0x40; // bit 1 (msb) set - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); - std::cout << VecToString(response) << std::endl; - uint8_t decrypted_response[16]; - uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, - 0xA5, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - // Provider sends pairing request - ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairingRequestAddress()); - - // Seeker sends their account key - WriteToAccountKey(); - - // BT negotatiates passkey 123456 (0x01E240) - uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; - uint8_t encrypted_passkey_block[16]; - nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, - kExpectedAesKey); - // Seeker sends the passkey to provider - nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, - sizeof(encrypted_passkey_block)); - - // Provider sends the passkey to seeker - response = nearby_test_fakes_GetGattNotifications().at(kPasskey); - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, - salt, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); - ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); - - std::cout << "Account keys: " - << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); -} - -TEST(NearbyFpClient, Pairing_SeekerInitiated_PairingSuccessful) { - uint8_t salt = 0xAB; - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); - nearby_test_fakes_SetRandomNumber(salt); - - // Provider sets the advertisement - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kDiscoverableAdvertisement)); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = 0x00; // bit 1 (msb) cleared - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // salt - for (int i = 8; i < 16; i++) { - request[i] = 0xCD + i; - } - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); - std::cout << VecToString(response) << std::endl; - uint8_t decrypted_response[16]; - uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, - 0xA5, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - // Seeker sends pairing request - nearby_test_fakes_SimulatePairing(kRemoteDevice); - - // BT negotatiates passkey 123456 (0x01E240) - uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; - uint8_t encrypted_passkey_block[16]; - nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, - kExpectedAesKey); - // Seeker sends the passkey to provider - nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, - sizeof(encrypted_passkey_block)); - - // Provider sends the passkey to seeker - response = nearby_test_fakes_GetGattNotifications().at(kPasskey); - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, - salt, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); - ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); - - // Seeker sends their account key - WriteToAccountKey(); - - std::cout << "Account keys: " - << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); -} - -TEST(NearbyFpClient, Pairing_SeekerInitiatedWriteKeyEarly_PairingSuccessful) { - uint8_t salt = 0xAB; - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); - nearby_test_fakes_SetRandomNumber(salt); - - // Provider sets the advertisement - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kDiscoverableAdvertisement)); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = 0x00; // bit 1 (msb) cleared - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // salt - for (int i = 8; i < 16; i++) { - request[i] = 0xCD + i; - } - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); - std::cout << VecToString(response) << std::endl; - uint8_t decrypted_response[16]; - uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, - 0xA5, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - // Seeker sends pairing request - nearby_test_fakes_SimulatePairing(kRemoteDevice); - - // Seeker sends their account key - WriteToAccountKey(); - - // BT negotatiates passkey 123456 (0x01E240) - uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; - uint8_t encrypted_passkey_block[16]; - nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, - kExpectedAesKey); - // Seeker sends the passkey to provider - nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, - sizeof(encrypted_passkey_block)); - - // Provider sends the passkey to seeker - response = nearby_test_fakes_GetGattNotifications().at(kPasskey); - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, - salt, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); - ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); - - std::cout << "Account keys: " - << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); -} - -static uint8_t GetType2KeyBasedPairingResponseFlags() { - // Not this is a dup of code under test. - uint8_t flags = 0; -#if NEARBY_FP_BLE_ONLY - flags |= 0x80; -#endif /*NEARBY_FP_BLE_ONLY*/ -#if NEARBY_FP_PREFER_BLE_BONDING - flags |= 0x40; -#endif /*NEARBY_FP_PREFER_BLE_BONDING*/ -#if NEARBY_FP_PREFER_LE_TRANSPORT - flags |= 0x20; -#endif /*NEARBY_FP_PREFER_LE_TRANSPORT*/ - return flags; -} - -TEST(NearbyFpClient, - SeekerSupportsBleDevicesSendExtendedKeybasedPairingResponseOneAddress) { - uint8_t salt = 0xAB; - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); - nearby_test_fakes_SetRandomNumber(salt); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = - 0x08; // Bit 4: 1 if the Seeker supports the BLE Device. 0 otherwise. - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); - std::cout << VecToString(response) << std::endl; - std::vector decrypted_response(16); - std::vector expected_decrypted_response = { - // 0x02 = Key-based Pairing Response - 0x02, - // flags - GetType2KeyBasedPairingResponseFlags(), - // Number of identity addresses. - 1, - // Presence identity address - 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, - // Random salt - salt, salt, salt, salt, salt, salt, salt}; - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response.data(), - kExpectedAesKey); - - ASSERT_EQ(decrypted_response, expected_decrypted_response); -} - -TEST(NearbyFpClient, - SeekerSupportsBleDevicesSendExtendedKeybasedPairingResponseTwoAddresses) { - uint8_t salt = 0xAB; - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - nearby_test_fakes_SetSecondaryPublicAddress(0xC0C1C2C3C4C5); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); - nearby_test_fakes_SetRandomNumber(salt); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = - 0x08; // Bit 4: 1 if the Seeker supports the BLE Device. 0 otherwise. - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); - std::cout << VecToString(response) << std::endl; - std::vector decrypted_response(16); - std::vector expected_decrypted_response = { - // 0x02 = Key-based Pairing Response - 0x02, - // flags - GetType2KeyBasedPairingResponseFlags(), - // Number of identity addresses. - 2, - // Presence identity address. - 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, - // Secondary identity address. - 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - // Random salt - salt}; - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response.data(), - kExpectedAesKey); - - ASSERT_EQ(decrypted_response, expected_decrypted_response); -} - -TEST(NearbyFpClient, Pair_AccountKeyStorageFull_AddsNewKey) { - nearby_fp_client_Init(NULL); - Set5AccountKeys(); - nearby_fp_LoadAccountKeys(); - - Pair(0x40); - - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(5, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); -} - -TEST(NearbyFpClient, ReadModelId) { - std::vector expected_model = {0x10, 0x11, 0x12}; - uint8_t model[3]; - size_t length = sizeof(model); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_GattReadModelId(model, &length)); - - ASSERT_EQ(sizeof(model), length); - ASSERT_EQ(expected_model, std::vector(model, model + length)); -} - -TEST(NearbyFpClient, ReadReadyPsm) { - std::vector expected_psm = -#if NEARBY_FP_PREFER_LE_TRANSPORT - {1, 0xAB, 0xCD}; -#else - {0, 0, 0}; -#endif - uint8_t psm[3]; - size_t length = sizeof(psm); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - nearby_test_fakes_SetPsm(0xABCD); - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_fakes_GattReadMessageStreamPsm(psm, &length)); - - ASSERT_EQ(sizeof(psm), length); - ASSERT_EQ(expected_psm, std::vector(psm, psm + length)); -} - -TEST(NearbyFpClient, ReadInvalidPsm) { - std::vector expected_psm = {0, 0, 0}; - uint8_t psm[3]; - size_t length = sizeof(psm); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - nearby_test_fakes_SetPsm(-1); - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_fakes_GattReadMessageStreamPsm(psm, &length)); - - ASSERT_EQ(sizeof(psm), length); - ASSERT_EQ(expected_psm, std::vector(psm, psm + length)); -} - -TEST(NearbyFpClient, Aes128Encrypt) { - uint8_t input[16] = {0xF3, 0x0F, 0x4E, 0x78, 0x6C, 0x59, 0xA7, 0xBB, - 0xF3, 0x87, 0x3B, 0x5A, 0x49, 0xBA, 0x97, 0xEA}; - uint8_t key[16] = {0xA0, 0xBA, 0xF0, 0xBB, 0x95, 0x1F, 0xF7, 0xB6, - 0xCF, 0x5E, 0x3F, 0x45, 0x61, 0xC3, 0x32, 0x1D}; - uint8_t expected_output[16] = {0xAC, 0x9A, 0x16, 0xF0, 0x95, 0x3A, - 0x3F, 0x22, 0x3D, 0xD1, 0x0C, 0xF5, - 0x36, 0xE0, 0x9E, 0x9C}; - uint8_t output[16]; - - ASSERT_EQ(kNearbyStatusOK, - nearby_test_fakes_Aes128Encrypt(input, output, key)); - - for (int i = 0; i < sizeof(expected_output); i++) { - ASSERT_EQ(expected_output[i], output[i]) << "Difference at position: " << i; - } -} - -TEST(NearbyFpClient, HmacSha256IncrementalOneChunk) { - const uint8_t kData[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, - 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, - 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, - 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; - const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; - const uint8_t kExpectedResult[] = { - 0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x61, 0x8B, 0x7D, - 0x87, 0x10, 0xD4, 0x41, 0x37, 0x09, 0xAB, 0x5D, 0xA2, 0x7C, 0xA2, - 0x6A, 0x66, 0xF5, 0x2E, 0x5A, 0xD4, 0xE8, 0x20, 0x90, 0x52}; - nearby_fp_HmacSha256Context context; - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HmacSha256Start(&context, kKey, sizeof(kKey))); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_HmacSha256Update(kData, sizeof(kData))); - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HmacSha256Finish(&context, kKey, sizeof(kKey))); - - ASSERT_THAT(context.hash, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, HmacSha256IncrementalTwoChunks) { - const uint8_t kData1[] = {0x00, 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0xEE}; - const uint8_t kData2[] = {0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, - 0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, - 0xAA, 0x44, 0xB9, 0xE5, 0x53, 0x6A, 0xF4, - 0x38, 0xE1, 0xE5, 0xC6}; - const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; - const uint8_t kExpectedResult[] = { - 0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x61, 0x8B, 0x7D, - 0x87, 0x10, 0xD4, 0x41, 0x37, 0x09, 0xAB, 0x5D, 0xA2, 0x7C, 0xA2, - 0x6A, 0x66, 0xF5, 0x2E, 0x5A, 0xD4, 0xE8, 0x20, 0x90, 0x52}; - nearby_fp_HmacSha256Context context; - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HmacSha256Start(&context, kKey, sizeof(kKey))); - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HmacSha256Update(kData1, sizeof(kData1))); - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HmacSha256Update(kData2, sizeof(kData2))); - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HmacSha256Finish(&context, kKey, sizeof(kKey))); - - ASSERT_THAT(context.hash, ElementsAreArray(kExpectedResult)); -} - -// Test cases from https://www.rfc-editor.org/rfc/rfc5869#appendix-A -TEST(NearbyFpClient, HkdfExtractSha256) { - const uint8_t kSalt[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c}; - const uint8_t kIkm[] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}; - const uint8_t kExpectedPrk[] = { - 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, - 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, - 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}; - uint8_t prk[SHA256_KEY_SIZE]; - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HkdfExtractSha256(prk, kSalt, sizeof(kSalt), kIkm, - sizeof(kIkm))); - - ASSERT_THAT(prk, ElementsAreArray(kExpectedPrk)); -} - -TEST(NearbyFpClient, HkdfExpandSha256) { - const uint8_t kInfo[] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, - 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}; - const uint8_t kPrk[] = {0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, - 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, - 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, - 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}; - constexpr size_t kOkmSize = 42; - const uint8_t kExpectedOkm[kOkmSize] = { - 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, - 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, - 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, - 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65}; - uint8_t okm[kOkmSize]; - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HkdfExpandSha256(okm, kOkmSize, kPrk, sizeof(kPrk), kInfo, - sizeof(kInfo))); - - ASSERT_THAT(okm, ElementsAreArray(kExpectedOkm)); -} - -TEST(NearbyFpClient, HkdfExtractSha256NoSalt) { - const uint8_t kIkm[] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}; - const uint8_t kExpectedPrk[] = { - 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, - 0x1d, 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, - 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}; - uint8_t prk[SHA256_KEY_SIZE]; - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_HkdfExtractSha256(prk, NULL, 0, kIkm, sizeof(kIkm))); - - ASSERT_THAT(prk, ElementsAreArray(kExpectedPrk)); -} - -TEST(NearbyFpClient, HkdfExpandSha256NoInfo) { - const uint8_t kPrk[] = {0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, - 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, - 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, - 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}; - constexpr size_t kOkmSize = 42; - const uint8_t kExpectedOkm[kOkmSize] = { - 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, - 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, - 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, - 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8}; - uint8_t okm[kOkmSize]; - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_HkdfExpandSha256(okm, kOkmSize, kPrk, - sizeof(kPrk), NULL, 0)); - - ASSERT_THAT(okm, ElementsAreArray(kExpectedOkm)); -} - -TEST(NearbyFpClient, HmacSha256) { - const uint8_t kData[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, - 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, - 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, - 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; - const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; - const uint8_t kExpectedResult[] = { - 0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x61, 0x8B, 0x7D, - 0x87, 0x10, 0xD4, 0x41, 0x37, 0x09, 0xAB, 0x5D, 0xA2, 0x7C, 0xA2, - 0x6A, 0x66, 0xF5, 0x2E, 0x5A, 0xD4, 0xE8, 0x20, 0x90, 0x52}; - uint8_t result[32]; - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_HmacSha256(result, kKey, sizeof(kKey), - kData, sizeof(kData))); - - ASSERT_THAT(result, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, AesCtr) { - uint8_t message[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, - 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, - 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, - 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; - const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; - const uint8_t kExpectedResult[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x53, 0x6F, 0x6D, 0x65, - 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, - 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_AesCtr(message, sizeof(message), kKey)); - - ASSERT_THAT(message, ElementsAreArray(kExpectedResult)); -} - -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA -TEST(NearbyFpClient, DecodeAdditionalData) { - uint8_t message[] = {0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x00, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, - 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, 0x2A, - 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, 0x53, - 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; - const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; - const uint8_t kExpectedResult[] = { - 0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x00, 0x01, 0x02, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, - 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, - 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_DecodeAdditionalData(message, sizeof(message), kKey)); - - ASSERT_THAT(message, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, EncodeAdditionalData) { - uint8_t message[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x53, 0x6F, - 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, - 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, - 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; - std::vector random_numbers = {0, 1, 2, 3, 4, 5, 6, 7}; - const uint8_t kKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; - const uint8_t kExpectedResult[] = { - 0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x00, 0x01, 0x02, - 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, 0x24, 0x83, 0x73, 0x80, - 0x52, 0xE4, 0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, - 0xB9, 0xE5, 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6}; - nearby_test_fakes_SetRandomNumberSequence(random_numbers); - - ASSERT_EQ(kNearbyStatusOK, - nearby_fp_EncodeAdditionalData(message, sizeof(message), kKey)); - - ASSERT_THAT(message, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, PairAndGetPersonalizedName) { - uint8_t name[] = {0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, - 0x20, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, - 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; - nearby_fp_client_Init(NULL); - ASSERT_EQ(kNearbyStatusOK, - nearby_platform_SaveValue(kStoredKeyPersonalizedName, name, - sizeof(name))); - - Pair(0x60); - - auto additional_data = - nearby_test_fakes_GetGattNotifications().at(kAdditionalData); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_DecodeAdditionalData( - additional_data.data(), additional_data.size(), - kExpectedAesKey)); - ASSERT_THAT(std::vector( - additional_data.begin() + ADDITIONAL_DATA_HEADER_SIZE, - additional_data.end()), - ElementsAreArray(name)); -} - -TEST(NearbyFpClient, PairAndSetPersonalizedName) { - uint8_t name[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x53, 0x6F, - 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, - 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, - 0x64, 0x70, 0x68, 0x6F, 0x6E, 0x65}; - nearby_fp_EncodeAdditionalData(name, sizeof(name), kSeekerAccountKey); - uint8_t request[16]; - request[0] = 0x10; // action request - request[1] = 0x40; // additional data characteristic - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - request[8] = 0; // message group, ignored - request[9] = 0; // message code, ignored - request[10] = 1; // data ID, personalized name - // salt - request[11] = 0x67; - request[12] = 0x89; - request[13] = 0xAB; - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kSeekerAccountKey); - nearby_fp_client_Init(NULL); - Pair(0x40); - - // Seeker wants to set personalized name - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - nearby_fp_fakes_ReceiveAdditionalData(name, sizeof(name)); - - uint8_t result[sizeof(name) - ADDITIONAL_DATA_HEADER_SIZE]; - size_t length = sizeof(result); - ASSERT_EQ(kNearbyStatusOK, nearby_platform_LoadValue( - kStoredKeyPersonalizedName, result, &length)); - ASSERT_EQ(length, sizeof(result)); - ASSERT_THAT(std::vector(name + ADDITIONAL_DATA_HEADER_SIZE, - name + sizeof(name)), - ElementsAreArray(result)); -} -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ - -#if NEARBY_FP_MESSAGE_STREAM -TEST(NearbyFpClient, RfcommConnected_NoBatteryInfo_SendsModelIdAndBleAddress) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); - - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - ASSERT_EQ(1, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -#if NEARBY_FP_RETROACTIVE_PAIRING -TEST(NearbyFpClient, RetroactivePair) { - nearby_fp_client_Init(NULL); - constexpr uint64_t kPeerAddress = 0xB0B1B2B3B4B5; - nearby_test_fakes_DevicePaired(kPeerAddress); - message_stream_events.clear(); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); - - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - uint8_t salt = 0xAB; - - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - nearby_test_fakes_SetRandomNumber(salt); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = 1 << 4; - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - // Seeker sends their account key - uint8_t encrypted_account_key_write_request[16]; - nearby_test_fakes_Aes128Encrypt( - kSeekerAccountKey, encrypted_account_key_write_request, kExpectedAesKey); - nearby_fp_fakes_ReceiveAccountKeyWrite( - encrypted_account_key_write_request, - sizeof(encrypted_account_key_write_request)); - - std::cout << "Account keys: " - << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); -} - -TEST(NearbyFpClient, RetroactivePairAfterInitialPair) { - constexpr uint64_t kPeerAddress = 0xB0B1B2B3B4B5; - uint8_t salt = 0xAB; - - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_Init(NULL)); - ASSERT_EQ(kNearbyStatusOK, nearby_test_fakes_SetAntiSpoofingKey( - kBobPrivateKey, kBobPublicKey)); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_DISCOVERABLE)); - nearby_test_fakes_SetRandomNumber(salt); - - // Provider sets the advertisement - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(kDiscoverableAdvertisement)); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = 0x40; // bit 1 (msb) set - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - auto response = nearby_test_fakes_GetGattNotifications().at(kKeyBasedPairing); - std::cout << VecToString(response) << std::endl; - uint8_t decrypted_response[16]; - uint8_t expected_decrypted_response[16] = {0x01, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, - 0xA5, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_decrypted_response[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - // Provider sends pairing request - ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairingRequestAddress()); - - // BT negotatiates passkey 123456 (0x01E240) - uint8_t raw_passkey_block[16] = {0x02, 0x01, 0xE2, 0x40}; - uint8_t encrypted_passkey_block[16]; - nearby_test_fakes_Aes128Encrypt(raw_passkey_block, encrypted_passkey_block, - kExpectedAesKey); - // Seeker sends the passkey to provider - nearby_fp_fakes_ReceivePasskey(encrypted_passkey_block, - sizeof(encrypted_passkey_block)); - - // Provider sends the passkey to seeker - response = nearby_test_fakes_GetGattNotifications().at(kPasskey); - nearby_test_fakes_Aes128Decrypt(response.data(), decrypted_response, - kExpectedAesKey); - uint8_t expected_passkey_block[16] = {0x03, 0x01, 0xE2, 0x40, salt, salt, - salt, salt, salt, salt, salt, salt, - salt, salt, salt, salt}; - for (int i = 0; i < sizeof(expected_decrypted_response); i++) { - ASSERT_EQ(expected_passkey_block[i], decrypted_response[i]) - << "Difference at position: " << i; - } - - ASSERT_EQ(123456, nearby_test_fakes_GetRemotePasskey()); - ASSERT_EQ(kRemoteDevice, nearby_test_fakes_GetPairedDevice()); - - // Seeker sends their account key - WriteToAccountKey(); - - std::cout << "Account keys: " - << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); - - message_stream_events.clear(); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); - - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - // Retroactive pairing - - request[0] = 0x00; // key-based pairing request - request[1] = 1 << 4; - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - - // Seeker responds - ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - // Seeker sends their account key - uint8_t encrypted_account_key_write_request[16]; - nearby_test_fakes_Aes128Encrypt( - kSeekerAccountKey2, encrypted_account_key_write_request, kExpectedAesKey); - ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveAccountKeyWrite( - encrypted_account_key_write_request, - sizeof(encrypted_account_key_write_request))); - - keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); -} - -TEST(NearbyFpClient, RetroactivePairTwice) { - nearby_fp_client_Init(NULL); - constexpr uint64_t kPeerAddress = 0xB0B1B2B3B4B5; - nearby_test_fakes_DevicePaired(kPeerAddress); - message_stream_events.clear(); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); - - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - uint8_t salt = 0xAB; - - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - nearby_test_fakes_SetRandomNumber(salt); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = 1 << 4; - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - - // Seeker responds - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - // Seeker sends their account key - uint8_t encrypted_account_key_write_request[16]; - nearby_test_fakes_Aes128Encrypt( - kSeekerAccountKey, encrypted_account_key_write_request, kExpectedAesKey); - ASSERT_EQ(kNearbyStatusOK, nearby_fp_fakes_ReceiveAccountKeyWrite( - encrypted_account_key_write_request, - sizeof(encrypted_account_key_write_request))); - - std::cout << "Account keys: " - << VecToString(nearby_test_fakes_GetRawAccountKeys()) << std::endl; - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); - - nearby_test_fakes_SetRandomNumber(salt); - request[0] = 0x00; // key-based pairing request - request[1] = 1 << 4; - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xB0; - request[9] = 0xB1; - request[10] = 0xB2; - request[11] = 0xB3; - request[12] = 0xB4; - request[13] = 0xB5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - - // Seeker responds - ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - // Seeker sends their account key - nearby_test_fakes_Aes128Encrypt( - kSeekerAccountKey2, encrypted_account_key_write_request, kExpectedAesKey); - ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveAccountKeyWrite( - encrypted_account_key_write_request, - sizeof(encrypted_account_key_write_request))); - - keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(1, keys.size()); - ASSERT_EQ(std::vector(kSeekerAccountKey, - kSeekerAccountKey + sizeof(kExpectedAesKey)), - keys.GetKey(0)); -} - -TEST(NearbyFpClient, RetroactivePairWrongBtAddress) { - nearby_fp_client_Init(NULL); - constexpr uint64_t kPeerAddress = 0xB0B1B2B3B4B5; - nearby_test_fakes_DevicePaired(kPeerAddress); - message_stream_events.clear(); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusOK); - - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - uint8_t salt = 0xAB; - - nearby_test_fakes_SetAntiSpoofingKey(kBobPrivateKey, kBobPublicKey); - nearby_test_fakes_SetRandomNumber(salt); - - uint8_t request[16]; - request[0] = 0x00; // key-based pairing request - request[1] = 1 << 4; - // Provider's public address - request[2] = 0xA0; - request[3] = 0xA1; - request[4] = 0xA2; - request[5] = 0xA3; - request[6] = 0xA4; - request[7] = 0xA5; - // Seeker's address - request[8] = 0xC0; - request[9] = 0xC1; - request[10] = 0xC2; - request[11] = 0xC3; - request[12] = 0xC4; - request[13] = 0xC5; - // salt - request[14] = 0xCD; - request[15] = 0xEF; - uint8_t encrypted[16 + 64]; - nearby_test_fakes_Aes128Encrypt(request, encrypted, kExpectedAesKey); - memcpy(encrypted + 16, kAlicePublicKey, 64); - - // Seeker responds - ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveKeyBasedPairingRequest( - encrypted, sizeof(encrypted))); - - // Seeker sends their account key - uint8_t encrypted_account_key_write_request[16]; - nearby_test_fakes_Aes128Encrypt( - kSeekerAccountKey, encrypted_account_key_write_request, kExpectedAesKey); - ASSERT_NE(kNearbyStatusOK, nearby_fp_fakes_ReceiveAccountKeyWrite( - encrypted_account_key_write_request, - sizeof(encrypted_account_key_write_request))); - - auto keys = nearby_test_fakes_GetAccountKeys(); - ASSERT_EQ(0, keys.size()); -} -#endif /* NEARBY_FP_RETROACTIVE_PAIRING */ - -TEST(NearbyFpClient, RfcommConnected_ClientDisconnects_EmitsDisconnectEvent) { - constexpr uint64_t kPeerAddress = 0x123456; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamDisconnected(kPeerAddress); - - ASSERT_EQ(2, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamDisconnectedEvent(kPeerAddress), - *message_stream_events[1]); -} - -TEST(NearbyFpClient, RfcommConnected_PeerSendsMessage_PassMessageToClientApp) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {101, 102, 0, 4, 81, 82, 83, 84}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(2, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); -} - -TEST(NearbyFpClient, - RfcommConnected_ConnectAndDisconnect_CanHandleManySessions) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {101, 102, 0, 4, 81, 82, 83, 84}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); - - for (int i = 1; i < NEARBY_MAX_RFCOMM_CONNECTIONS + 10; i++) { - nearby_test_fakes_MessageStreamConnected(kPeerAddress + i); - nearby_test_fakes_MessageStreamDisconnected(kPeerAddress + i); - } - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - int events = message_stream_events.size(); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[events - 2]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[events - 1]); -} - -#if NEARBY_MAX_RFCOMM_CONNECTIONS > 1 -TEST(NearbyFpClient, RfcommConnected_TwoInterleavedConnections_ParsesMessages) { - constexpr uint64_t kPeerAddress1 = 0x123456; - constexpr uint8_t kPeerMessage1[] = {101, 102, 0, 4, 81, 82, 83, 84}; - const nearby_event_MessageStreamReceived kExpectedMessage1 = { - .peer_address = kPeerAddress1, - .message_group = kPeerMessage1[0], - .message_code = kPeerMessage1[1], - .length = kPeerMessage1[2] * 256 + kPeerMessage1[3], - .data = (uint8_t*)kPeerMessage1 + 4, - }; - constexpr uint64_t kPeerAddress2 = 0x7890ab; - constexpr uint8_t kPeerMessage2[] = {201, 202, 0, 5, 91, 92, 93, 94, 95}; - const nearby_event_MessageStreamReceived kExpectedMessage2 = { - .peer_address = kPeerAddress2, - .message_group = kPeerMessage2[0], - .message_code = kPeerMessage2[1], - .length = kPeerMessage2[2] * 256 + kPeerMessage2[3], - .data = (uint8_t*)kPeerMessage2 + 4, - }; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnimplemented); - nearby_test_fakes_MessageStreamConnected(kPeerAddress1); - nearby_test_fakes_MessageStreamConnected(kPeerAddress2); - - // Send the messages byte by byte, interleaving bytes from both connections - // to verify that the parses handles the streams separately - for (int i = 0; i < std::max(sizeof(kPeerMessage1), sizeof(kPeerMessage2)); - i++) { - if (i < sizeof(kPeerMessage1)) { - nearby_test_fakes_MessageStreamReceived(kPeerAddress1, kPeerMessage1 + i, - 1); - } - if (i < sizeof(kPeerMessage2)) { - nearby_test_fakes_MessageStreamReceived(kPeerAddress2, kPeerMessage2 + i, - 1); - } - } - - ASSERT_EQ(4, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress1), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress2), - *message_stream_events[1]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage1), - *message_stream_events[2]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage2), - *message_stream_events[3]); -} -#endif /* NEARBY_MAX_RFCOMM_CONNECTIONS > 1 */ - -TEST(NearbyFpClient, SendMessageStreamMessage) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr nearby_message_stream_Message kMessage{ - .message_group = 20, - .message_code = 10, - }; - constexpr uint8_t kExpectedRfcommOutput[] = {20, 10, 0, 0}; - nearby_fp_client_Init(&kClientCallbacks); - - nearby_fp_client_SendMessage(kPeerAddress, &kMessage); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, SendAck) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr nearby_event_MessageStreamReceived kMessage{ - .peer_address = kPeerAddress, - .message_group = 20, - .message_code = 10, - }; - constexpr uint8_t kExpectedRfcommOutput[] = {0xFF, 1, 0, 2, 20, 10}; - nearby_fp_client_Init(&kClientCallbacks); - - nearby_fp_client_SendAck(&kMessage); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, SendNack) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kFailReason = 30; - constexpr nearby_event_MessageStreamReceived kMessage{ - .peer_address = kPeerAddress, - .message_group = 20, - .message_code = 10, - }; - constexpr uint8_t kExpectedRfcommOutput[] = {0xFF, 2, 0, 3, - kFailReason, 20, 10}; - nearby_fp_client_Init(&kClientCallbacks); - - nearby_fp_client_SendNack(&kMessage, kFailReason); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -TEST(NearbyFpClient, TimerTriggered_RotatesBleAddress) { - uint64_t firstAddress, secondAddress, thirdAddress; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetInPairingMode(false); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); - firstAddress = nearby_platform_GetBleAddress(); - - nearby_test_fakes_SetRandomNumber(30); - nearby_test_fakes_SetCurrentTimeMs(nearby_test_fakes_GetNextTimerMs()); - secondAddress = nearby_platform_GetBleAddress(); - nearby_test_fakes_SetRandomNumber(31); - nearby_test_fakes_SetCurrentTimeMs(nearby_test_fakes_GetNextTimerMs()); - thirdAddress = nearby_platform_GetBleAddress(); - - ASSERT_NE(firstAddress, secondAddress); - ASSERT_NE(secondAddress, thirdAddress); -} - -TEST(NearbyFpClient, TimerTriggered_InPairingMode_DoesntRotateBleAddress) { - uint64_t firstAddress, secondAddress, thirdAddress; - - nearby_test_fakes_SetRandomNumber(0); - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetInPairingMode(false); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE); - firstAddress = nearby_platform_GetBleAddress(); - - nearby_test_fakes_SetInPairingMode(true); - nearby_test_fakes_SetRandomNumber(30); - nearby_test_fakes_SetCurrentTimeMs(nearby_test_fakes_GetNextTimerMs()); - secondAddress = nearby_platform_GetBleAddress(); - - nearby_test_fakes_SetInPairingMode(false); - nearby_test_fakes_SetRandomNumber(31); - nearby_test_fakes_SetCurrentTimeMs(nearby_test_fakes_GetNextTimerMs()); - thirdAddress = nearby_platform_GetBleAddress(); - - ASSERT_EQ(firstAddress, secondAddress); - ASSERT_NE(secondAddress, thirdAddress); -} - -TEST(NearbyFpClient, AdvertiseDisoverable_RotatesBleAddress) { - uint64_t firstAddress; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetInPairingMode(false); - firstAddress = nearby_platform_GetBleAddress(); - - nearby_test_fakes_SetRandomNumber(32); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); - - ASSERT_NE(firstAddress, nearby_platform_GetBleAddress()); -} - -TEST(NearbyFpClient, - AdvertiseDisoverable_InPairingMode_DoesntRotatesBleAddress) { - uint64_t firstAddress; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetInPairingMode(true); - firstAddress = nearby_platform_GetBleAddress(); - - nearby_test_fakes_SetRandomNumber(32); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); - - ASSERT_EQ(firstAddress, nearby_platform_GetBleAddress()); -} - -TEST(NearbyFpClient, - ChangeAdvertisementType_InPairingMode_DoesntRotateBleAddress) { - uint64_t firstAddress; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetInPairingMode(true); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE); - firstAddress = nearby_platform_GetBleAddress(); - - nearby_test_fakes_SetRandomNumber(34); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_DISCOVERABLE); - - ASSERT_EQ(firstAddress, nearby_platform_GetBleAddress()); -} - -TEST(NearbyFpClient, ChangeAdvertisementFlags_DoesntRotateBleAddress) { - uint64_t firstAddress; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetInPairingMode(false); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE); - firstAddress = nearby_platform_GetBleAddress(); - - nearby_test_fakes_SetRandomNumber(36); - nearby_fp_client_SetAdvertisement( - NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR); - - ASSERT_EQ(firstAddress, nearby_platform_GetBleAddress()); -} - -TEST(NearbyFpClient, GenerateSassAdvertisement) { - constexpr size_t kBufferSize = 4; - uint8_t buffer[kBufferSize]; - constexpr uint8_t devices_bitmap[] = {0x09}; - constexpr uint8_t kExpectedResult[] = {0x35, 0x85, 0x38, 0x09}; - size_t sass_length = nearby_fp_GenerateSassAdvertisement( - buffer, kBufferSize, nearby_fp_GetSassConnectionState(), 0x38, - devices_bitmap, sizeof(devices_bitmap)); - - ASSERT_EQ(sass_length, kBufferSize); - ASSERT_THAT(buffer, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, GenerateAccountFilterNoSass) { - std::vector random_numbers = {0xC7, 0xC8}; - constexpr uint8_t kExpectedResult[] = {13, 0x16, 0x2C, 0xFE, 0x00, - 0x52, 0x8E, 0x83, 0x84, 0x30, - 0x0C, 0x21, 0xC7, 0xC8}; - uint8_t advertisement[] = {13, 0x16, 0x2C, 0xFE, 0x00, 0x52, 0x8E, - 0x83, 0x84, 0x30, 0x0C, 0x21, 0xC7, 0xC8}; - uint8_t account_key1[] = {0x04, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - uint8_t account_key2[] = {0x04, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, - 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key1), - AccountKeyPair(kRemoteDevice, account_key2)}; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAccountKeys(account_keys); - nearby_fp_LoadAccountKeys(); - - nearby_fp_SetBloomFilter(advertisement, - /* use_sass_format= */ false, NULL); - - ASSERT_THAT(advertisement, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, GenerateAccountFilterOneKeyNotInUse) { - std::vector random_numbers = {0xC7, 0xC8}; - constexpr uint8_t kExpectedResult[] = {17, 0x16, 0x2C, 0xFE, 0x10, 0x40, - 0x42, 0x80, 0x81, 0x01, 0x21, 0xC7, - 0xC8, 0x46, 0x6E, 0x39, 0xCB, 0x21}; - uint8_t advertisement[] = {17, 0x16, 0x2C, 0xFE, 0x00, 0x40, - 0, 0, 0, 0, 0x21, 0xC7, - 0xC8, 0x46, 0x6E, 0x39, 0xCB, 0x21}; - uint8_t account_key[] = {0x04, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key)}; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAccountKeys(account_keys); - nearby_fp_LoadAccountKeys(); - - nearby_fp_SetBloomFilter(advertisement, - /* use_sass_format= */ true, NULL); - - ASSERT_THAT(advertisement, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, GenerateAccountFilterOneKeyInUse) { - std::vector random_numbers = {0xC7, 0xC8}; - constexpr uint8_t kExpectedResult[] = {17, 0x16, 0x2C, 0xFE, 0x10, 0x40, - 0x81, 0x28, 0xA8, 0x04, 0x21, 0xC7, - 0xC8, 0x46, 0x6E, 0x39, 0xCB, 0x21}; - uint8_t advertisement[] = {17, 0x16, 0x2C, 0xFE, 0, 0x40, - 0, 0, 0, 0, 0x21, 0xC7, - 0xC8, 0x46, 0x6E, 0x39, 0xCB, 0x21}; - uint8_t account_key[] = {0x04, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key)}; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAccountKeys(account_keys); - nearby_fp_LoadAccountKeys(); - - nearby_fp_SetBloomFilter(advertisement, - /* use_sass_format= */ true, account_key); - - ASSERT_THAT(advertisement, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, GenerateAccountFilterSassTwoKeys) { - std::vector random_numbers = {0xC7, 0xC8}; - constexpr uint8_t kExpectedResult[] = { - 18, 0x16, 0x2C, 0xFE, 0x10, 0x50, 0x41, 0x90, 0x34, 0x80, - 0xA2, 0x21, 0xC7, 0xC8, 0x46, 0xE8, 0xF0, 0x50, 0x69}; - uint8_t advertisement[] = {18, 0x16, 0x2C, 0xFE, 0x10, 0x50, 0x41, - 0x90, 0x34, 0x80, 0xA2, 0x21, 0xC7, 0xC8, - 0x46, 0xE8, 0xF0, 0x50, 0x69}; - uint8_t account_key1[] = {0x04, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - uint8_t account_key2[] = {0x04, 0x12, 0x13, 0x14, 0x55, 0x66, 0x77, 0x88, - 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; - std::vector account_keys{ - AccountKeyPair(kRemoteDevice, account_key1), - AccountKeyPair(kRemoteDevice, account_key2)}; - nearby_fp_client_Init(NULL); - nearby_test_fakes_SetAccountKeys(account_keys); - nearby_fp_LoadAccountKeys(); - - nearby_fp_SetBloomFilter(advertisement, - /* use_sass_format= */ true, account_key2); - - ASSERT_THAT(advertisement, ElementsAreArray(kExpectedResult)); -} - -TEST(NearbyFpClient, EncryptRrf) { - constexpr uint8_t kSassAdvertisement[] = {0x35, 0x00, 0x38, 0x09}; - constexpr uint8_t kExpectedResult[] = {0x46, 0x6E, 0x39, 0xCB, 0x21}; - constexpr size_t kBufferSize = RRF_HEADER_SIZE + sizeof(kSassAdvertisement); - uint8_t buffer[kBufferSize]; - constexpr uint8_t kAccountKey[] = {0x04, 0x22, 0x33, 0x44, 0x55, 0x66, - 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, - 0xCC, 0xDD, 0xEE, 0xFF}; - constexpr uint8_t kSaltField[] = {0x21, 0xC7, 0xC8}; - memcpy(buffer + RRF_HEADER_SIZE, kSassAdvertisement, - sizeof(kSassAdvertisement)); - - nearby_platform_status status = nearby_fp_EncryptRandomResolvableField( - buffer, kBufferSize, kAccountKey, kSaltField); - - ASSERT_EQ(status, kNearbyStatusOK); - ASSERT_THAT(buffer, ElementsAreArray(kExpectedResult)); -} - -#ifdef NEARBY_FP_ENABLE_SASS -TEST(NearbyFpClient, - SassConnected_ReceiveGetCapability_SendsCapabilityResponse) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {0x07, 0x10, 0, 0}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Battery level - 3, 3, 0, 3, 0xd5, 0xd0, 0xda, - // Battery remaining time - 3, 4, 0, 1, 100, - // Capability response - 7, 0x11, 0, 4, 1, 1, 208, 0}; - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - message_stream_events.clear(); - nearby_test_fakes_BatteryTime(100); - nearby_test_fakes_GetRfcommOutput(kPeerAddress).clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(2, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -constexpr uint8_t kInUseMessage[] = {0x07, 0x41, 0, 22, 'i', 'n', '-', - 'u', 's', 'e', 0xC0, 0xC1, 0xC2, 0xC3, - 0xC4, 0xC5, 0xC6, 0xC7, 0x70, 0x69, 0xd6, - 0xc5, 0x06, 0xa4, 0x94, 0x32}; - -TEST(NearbyFpClient, SassConnected_IndicateValidInUseKey_SendsAck) { - constexpr uint64_t kPeerAddress = 0x123456; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kInUseMessage[0], - .message_code = kInUseMessage[1], - .length = kInUseMessage[2] * 256 + kInUseMessage[3], - .data = (uint8_t*)kInUseMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x41}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - ASSERT_EQ(2, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, SassConnected_IndicateInvalidInUseKey_SendsNack) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {0x07, 0x41, 0, 22, 'i', 'n', '-', - 'u', 's', 'e', 0xFF, 0xC1, 0xC2, 0xC3, - 0xC4, 0xC5, 0xC6, 0xC7, 0x70, 0x69, 0xd6, - 0xc5, 0x06, 0xa4, 0x94, 0x32}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // NACK - 0xFF, 2, 0, 3, 0, 0x07, 0x41}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(2, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, SassConnected_SetMultipointState) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {0x07, 0x12, 0, 17, 1, 0xC0, 0xC1, - 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xb7, - 0x2f, 0x61, 0xb4, 0xe8, 0x92, 0xe1, 0x44}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x12}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(3, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[2]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_TRUE(nearby_platform_IsMultipointOn()); -} - -TEST(NearbyFpClient, SassConnected_SetSwitchingPreference) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kFlags = 0xAB; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x20, 0, 18, kFlags, 0, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, - 0xC5, 0xC6, 0xC7, 0x8d, 0x03, 0x9d, 0xb0, 0x3d, 0x4b, 0x93, 0x7a}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x20}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(3, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[2]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_EQ(kFlags, nearby_platform_GetSwitchingPreference()); -} - -TEST( - NearbyFpClient, - SassConnected_ReceiveGetSwitchingPreference_SendsSwitchingPreferenceResponse) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {0x07, 0x21, 0, 0}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Switching preference response - 7, 0x22, 0, 2, 0, 0}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(2, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[1]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, SassConnected_SwitchActiveAudioSourceToThisPeer) { - constexpr uint64_t kPeerAddress = 0x123456; - // Bit 0 (MSB) is set. - constexpr uint8_t kFlags = 0xAB; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x30, 0, 17, kFlags, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0x30, 0x75, 0x28, 0xdd, 0x98, 0x27, 0x07, 0x95}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x30}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(3, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[2]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_EQ(kPeerAddress, - nearby_test_fakes_GetSassSwitchActiveSourcePeerAddress()); - ASSERT_EQ(kFlags, nearby_test_fakes_GetSassSwitchActiveSourceFlags()); - ASSERT_EQ(kPeerAddress, - nearby_test_fakes_GetSassSwitchActiveSourcePreferredAudioSource()); -} - -TEST(NearbyFpClient, - SassConnected_SwitchActiveAudioSourceToAnotherSourceWithSameKey) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint64_t kPeerWithSameKey = 0x17890a; - // Bit 0 (MSB) is not set. - constexpr uint8_t kFlags = 0x0B; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x30, 0, 17, kFlags, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0x55, 0xf2, 0x2d, 0x76, 0x05, 0x83, 0x5f, 0x52}; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x30}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - nearby_test_fakes_MessageStreamConnected(kPeerWithSameKey); - nearby_test_fakes_MessageStreamReceived(kPeerWithSameKey, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_EQ(kPeerAddress, - nearby_test_fakes_GetSassSwitchActiveSourcePeerAddress()); - ASSERT_EQ(kFlags, nearby_test_fakes_GetSassSwitchActiveSourceFlags()); - ASSERT_EQ(kPeerWithSameKey, - nearby_test_fakes_GetSassSwitchActiveSourcePreferredAudioSource()); -} - -TEST(NearbyFpClient, - SassConnected_SwitchActiveAudioSourceToAnotherSourceWithDifferentKey) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint64_t kPeerWithDifferentKey = 0x17890a; - // Bit 0 (MSB) is not set. - constexpr uint8_t kFlags = 0x0B; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x30, 0, 17, kFlags, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0x55, 0xf2, 0x2d, 0x76, 0x05, 0x83, 0x5f, 0x52}; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x30}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - nearby_test_fakes_MessageStreamConnected(kPeerWithDifferentKey); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_EQ(kPeerAddress, - nearby_test_fakes_GetSassSwitchActiveSourcePeerAddress()); - ASSERT_EQ(kFlags, nearby_test_fakes_GetSassSwitchActiveSourceFlags()); - ASSERT_EQ(kPeerWithDifferentKey, - nearby_test_fakes_GetSassSwitchActiveSourcePreferredAudioSource()); -} - -TEST(NearbyFpClient, SassConnected_SwitchActiveAudioSourceToUnknownSource) { - constexpr uint64_t kPeerAddress = 0x123456; - // Bit 0 (MSB) is not set. - constexpr uint8_t kFlags = 0x0B; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x30, 0, 17, kFlags, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0x55, 0xf2, 0x2d, 0x76, 0x05, 0x83, 0x5f, 0x52}; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x30}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_EQ(kPeerAddress, - nearby_test_fakes_GetSassSwitchActiveSourcePeerAddress()); - ASSERT_EQ(kFlags, nearby_test_fakes_GetSassSwitchActiveSourceFlags()); - ASSERT_EQ(0, - nearby_test_fakes_GetSassSwitchActiveSourcePreferredAudioSource()); -} - -TEST(NearbyFpClient, SassConnected_SwitchBackToDisconnectedDevice) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kFlags = 0xAB; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x31, 0, 17, kFlags, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0x30, 0x75, 0x28, 0xdd, 0x98, 0x27, 0x07, 0x95}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x31}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(3, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[2]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_EQ(kPeerAddress, nearby_test_fakes_GetSassSwitchBackPeerAddress()); - ASSERT_EQ(kFlags, nearby_test_fakes_GetSassSwitchBackFlags()); -} - -TEST(NearbyFpClient, - SassConnected_ReceiveGetConnectionStatus_SendsConnectionStatusResponse) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kPeerMessage[] = {0x07, 0x33, 0, 0}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // Connection status response - 7, 0x34, 0, 12, 0x00, 0xaf, 0x75, 0x14, kSalt, kSalt, kSalt, kSalt, kSalt, - kSalt, kSalt, kSalt}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(3, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[2]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST( - NearbyFpClient, - SassConnected_ReceiveGetConnectionStatus_SendsConnectionStatusResponseNonSassActive) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint64_t kPeerNonSassAddress = 0x654321; - constexpr uint8_t kPeerMessage[] = {0x07, 0x33, 0, 0}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // Connection status response - 7, 0x34, 0, 12, 0x02, 0xaf, 0x75, 0x14, kSalt, kSalt, kSalt, kSalt, kSalt, - kSalt, kSalt, kSalt}; - - nearby_fp_client_Init(&kClientCallbacks); - nearby_test_fakes_DevicePaired(kPeerNonSassAddress); - nearby_test_fakes_SetActiveAudioSource(kPeerNonSassAddress); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(3, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[2]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); -} - -TEST(NearbyFpClient, SassConnected_NotifySassInitiatedConnection) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kFlags = 0xAB; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x40, 0, 17, kFlags, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0x30, 0x75, 0x28, 0xdd, 0x98, 0x27, 0x07, 0x95}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x40}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(3, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[2]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_EQ(kPeerAddress, - nearby_test_fakes_GetSassNotifyInitiatedConnectionPeerAddress()); - ASSERT_EQ(kFlags, nearby_test_fakes_GetSassNotifyInitiatedConnectionFlags()); -} - -TEST(NearbyFpClient, SassConnected_SendCustomData) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint64_t kSecondPeerAddress = 0x89ABCD; - constexpr uint8_t kCustomData = 0xAB; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x42, 0, 17, kCustomData, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0x30, 0x75, 0x28, 0xdd, 0x98, 0x27, 0x07, 0x95}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Connection state - 7, 0x34, 0, 12, 1, 0xaf, 0x75, 0x14, kSalt, kSalt, kSalt, kSalt, kSalt, - kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // Connection state - 7, 0x34, 0, 12, 1, 0xaf, 0x75, 0x14, kSalt, kSalt, kSalt, kSalt, kSalt, - kSalt, kSalt, kSalt, - // Connection state - 7, 0x34, 0, 12, 1, 0xaf, 0xde, 0x14, kSalt, kSalt, kSalt, kSalt, kSalt, - kSalt, kSalt, kSalt, - // Send custom data ACK - 0xFF, 1, 0, 2, 0x07, 0x42}; - constexpr uint8_t kSecondPeerExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Connection state - 7, 0x34, 0, 12, 0, 0xaf, 0x75, 0x14, kSalt, kSalt, kSalt, kSalt, kSalt, - kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // Connection State - 7, 0x34, 0, 12, 0, 0xaf, 0xde, 0x14, kSalt, kSalt, kSalt, kSalt, kSalt, - kSalt, kSalt, kSalt}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetActiveAudioSource(kPeerAddress); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_SASS); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - nearby_test_fakes_MessageStreamConnected(kSecondPeerAddress); - nearby_test_fakes_MessageStreamReceived(kSecondPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(5, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[4]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_THAT( - kSecondPeerExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kSecondPeerAddress))); -} - -TEST(NearbyFpClient, SassConnected_SetDropConnectionTarget) { - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint8_t kFlags = 0xAB; - constexpr uint8_t kPeerMessage[] = { - 0x07, 0x43, 0, 17, kFlags, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0x30, 0x75, 0x28, 0xdd, 0x98, 0x27, 0x07, 0x95}; - const nearby_event_MessageStreamReceived kExpectedMessage = { - .peer_address = kPeerAddress, - .message_group = kPeerMessage[0], - .message_code = kPeerMessage[1], - .length = kPeerMessage[2] * 256 + kPeerMessage[3], - .data = (uint8_t*)kPeerMessage + 4, - }; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0xFF, 1, 0, 2, 0x07, 0x43}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kPeerMessage, - sizeof(kPeerMessage)); - - ASSERT_EQ(3, message_stream_events.size()); - ASSERT_EQ(MessageStreamConnectedEvent(kPeerAddress), - *message_stream_events[0]); - ASSERT_EQ(MessageStreamReceivedEvent(&kExpectedMessage), - *message_stream_events[2]); - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_EQ(kPeerAddress, - nearby_test_fakes_GetSassDropConnectionTargetPeerAddress()); - ASSERT_EQ(kFlags, nearby_test_fakes_GetSassDropConnectionTargetFlags()); -} - -TEST(NearbyFpClient, CreateSassAdvertiment_SeekerConnected_UsesInUseKey) { - constexpr uint64_t kPeerAddress = 0x123456; - std::map> expected_results = { - { - 1, // Salt size - {0x10, 0x16, 0x2c, 0xfe, 0x10, 0x42, 0x08, 0x20, 0x44, 0x11, - 0x11, kSalt, 0x46, 0xdb, 0x29, 0x6a, 0xb3, 2, 0x0a, kTxPower}, - }, - {2, // Salt size - {0x11, 0x16, 0x2c, 0xfe, 0x10, 0x42, 0x01, 0x11, 0x90, 0x60, 0x21, - kSalt, kSalt, 0x46, 0xdf, 0xa3, 0x4b, 0xed, 2, 0x0a, kTxPower}}}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_SASS); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(expected_results[NEARBY_FP_SALT_SIZE])); -} - -TEST(NearbyFpClient, - CreateSassAdvertiment_AdvertisingThenSeekerConnects_UsesInUseKey) { - constexpr uint64_t kPeerAddress = 0x123456; - std::map> expected_results = { - { - 1, // Salt size - {0x10, 0x16, 0x2c, 0xfe, 0x10, 0x42, 0x08, 0x20, 0x44, 0x11, - 0x11, kSalt, 0x46, 0xdb, 0x29, 0x6a, 0xb3, 2, 0x0a, kTxPower}, - }, - {2, // Salt size - {0x11, 0x16, 0x2c, 0xfe, 0x10, 0x42, 0x01, 0x11, 0x90, 0x60, 0x21, - kSalt, kSalt, 0x46, 0xdf, 0xa3, 0x4b, 0xed, 2, 0x0a, kTxPower}}}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_SASS); - - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(expected_results[NEARBY_FP_SALT_SIZE])); -} - -TEST(NearbyFpClient, CreateSassAdvertiment_NoSeeker_UsesLastUsedKey) { - std::map> expected_results = { - { - 1, // Salt size - {0x10, 0x16, 0x2c, 0xfe, 0x10, 0x42, 0x01, 0x03, 0x04, 0xa0, - 0x11, kSalt, 0x46, 0xdb, 0x29, 0x6a, 0xb3, 2, 0x0a, kTxPower}, - }, - {2, // Salt size - {0x11, 0x16, 0x2c, 0xfe, 0x10, 0x42, 0x02, 0x20, 0x82, 0x34, 0x21, - kSalt, kSalt, 0x46, 0xdf, 0xa3, 0x4b, 0xed, 2, 0x0a, kTxPower}}}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_SASS); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(expected_results[NEARBY_FP_SALT_SIZE])); -} - -TEST(NearbyFpClient, CreateSassAdvertiment_SeekerDisconnects_UsesLastUsedKey) { - constexpr uint64_t kPeerAddress = 0x123456; - std::map> expected_results = { - { - 1, // Salt size - {0x10, 0x16, 0x2c, 0xfe, 0x10, 0x42, 0x01, 0x03, 0x04, 0xa0, - 0x11, kSalt, 0x46, 0xdb, 0x29, 0x6a, 0xb3, 2, 0x0a, kTxPower}, - }, - {2, // Salt size - {0x11, 0x16, 0x2c, 0xfe, 0x10, 0x42, 0x02, 0x20, 0x82, 0x34, 0x21, - kSalt, kSalt, 0x46, 0xdf, 0xa3, 0x4b, 0xed, 2, 0x0a, kTxPower}}}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - nearby_fp_client_SetAdvertisement(NEARBY_FP_ADVERTISEMENT_NON_DISCOVERABLE | - NEARBY_FP_ADVERTISEMENT_SASS); - - nearby_test_fakes_MessageStreamDisconnected(kPeerAddress); - - ASSERT_THAT(nearby_test_fakes_GetAdvertisement(), - ElementsAreArray(expected_results[NEARBY_FP_SALT_SIZE])); -} - -TEST(NearbyFpClient, MultipointSwitch_WithName_SendsNotificationToAllSeekers) { - constexpr uint8_t kReason = 2; - const char* kName = "SEEKER"; - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint64_t kSecondPeerAddress = 0x89ABCD; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // Notify multipoint switch event - 0x07, 0x32, 0x00, 0x08, 0x02, 0x02, 'S', 'E', 'E', 'K', 'E', 'R'}; - constexpr uint8_t kSecondPeerExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0x07, 0x32, 0x00, 0x08, 0x02, 0x01, 'S', 'E', 'E', 'K', 'E', 'R'}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - nearby_test_fakes_MessageStreamConnected(kSecondPeerAddress); - nearby_test_fakes_MessageStreamReceived(kSecondPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_SassMultipointSwitch(kReason, kSecondPeerAddress, kName); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_THAT( - kSecondPeerExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kSecondPeerAddress))); -} - -TEST(NearbyFpClient, - MultipointSwitch_WithoutName_SendsNotificationToAllSeekers) { - constexpr uint8_t kReason = 2; - constexpr uint64_t kPeerAddress = 0x123456; - constexpr uint64_t kSecondPeerAddress = 0x8909AF; - constexpr uint8_t kExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // Notify multipoint switch event - 0x07, 0x32, 0x00, 0x06, 0x02, 0x02, '0', '9', 'A', 'F'}; - constexpr uint8_t kSecondPeerExpectedRfcommOutput[] = { - // Model Id - 3, 1, 0, 3, 0x10, 0x11, 0x12, - // Ble Address - 3, 2, 0, 6, 0x6b, 0xab, 0xab, 0xab, 0xab, 0xab, - // Session nonce - 3, 10, 0, 8, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, kSalt, - // Indicate in-use key ACK - 0xFF, 1, 0, 2, 0x07, 0x41, - // ACK - 0x07, 0x32, 0x00, 0x06, 0x02, 0x01, '0', '9', 'A', 'F'}; - - nearby_fp_client_Init(&kClientCallbacks); - Pair(0x40); - nearby_test_fakes_SetGetBatteryInfoResult(kNearbyStatusUnsupported); - message_stream_events.clear(); - nearby_test_fakes_MessageStreamConnected(kPeerAddress); - nearby_test_fakes_MessageStreamReceived(kPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - nearby_test_fakes_MessageStreamConnected(kSecondPeerAddress); - nearby_test_fakes_MessageStreamReceived(kSecondPeerAddress, kInUseMessage, - sizeof(kInUseMessage)); - - nearby_test_fakes_SassMultipointSwitch(kReason, kSecondPeerAddress, NULL); - - ASSERT_THAT( - kExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kPeerAddress))); - ASSERT_THAT( - kSecondPeerExpectedRfcommOutput, - ElementsAreArray(nearby_test_fakes_GetRfcommOutput(kSecondPeerAddress))); -} -#endif /* NEARBY_FP_ENABLE_SASS */ - -#pragma GCC diagnostic pop - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/embedded/common/source/mbedtls/gen_secret.c b/embedded/common/source/mbedtls/gen_secret.c deleted file mode 100644 index 2f904225..00000000 --- a/embedded/common/source/mbedtls/gen_secret.c +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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. - -// -// gen_secret module -// -// Implements the nearby_platform_GenSec256r1Secret() function, using the -// MBEDTLS package developed by ARM. -// -// To use the package, uncomment the NEARBY_PLATFORM_USE_MBEDTLS define in -// config.mk. -// -// This routine was separated from the mbedtls.c code because an implementation -// may need to implement the shared secret function using a hardware embedded -// key. In such an implementation, the actual private key is not directly -// accessable, but rather the shared secret is generated using the public key -// and the sequestered private key without ever revealing the private key in -// code. -// - -#define MBEDTLS_ALLOW_PRIVATE_ACCESS - -#include -#include -#include -#include -#include /* generic interface */ -#include -#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) -#include -#endif - -#include -#include - -#ifndef NEARBY_PLATFORM_HAS_SE -static int crypto_rand(void* const seed, uint8_t* const out, - size_t const size) { - (void)seed; - for (size_t i = 0; i < size; i++) { - out[i] = rand() % UINT8_MAX; - } - return 0; -} - -/** - * Generates a shared sec256p1 secret using remote party public key and this - * device's private key. - */ -nearby_platform_status nearby_platform_GenSec256r1Secret( - const uint8_t remote_party_public_key[64], uint8_t shared_secret[32]) { - nearby_platform_status status = kNearbyStatusError; - mbedtls_ecp_group grp; - mbedtls_ecp_point pub; - mbedtls_mpi prv; - mbedtls_mpi secret; - - mbedtls_ecp_group_init(&grp); - mbedtls_ecp_point_init(&pub); - mbedtls_mpi_init(&prv); - mbedtls_mpi_init(&secret); - - mbedtls_mpi_uint p = 1; - pub.Z.p = &p; - pub.Z.n = 1; - - const uint8_t* pkp; - - pkp = nearby_platform_GetAntiSpoofingPrivateKey(); - if (!pkp) { - goto exit; - } - if (mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1) != 0) goto exit; - if (mbedtls_mpi_read_binary(&pub.X, remote_party_public_key, 32) != 0) - goto exit; - if (mbedtls_mpi_read_binary(&pub.Y, remote_party_public_key + 32, 32) != 0) - goto exit; - if (mbedtls_mpi_read_binary(&prv, pkp, 32) != 0) goto exit; - if ((mbedtls_ecdh_compute_shared(&grp, &secret, &pub, &prv, crypto_rand, - NULL)) != 0) - goto exit; - if (mbedtls_mpi_write_binary(&secret, shared_secret, 32) != 0) goto exit; - - status = kNearbyStatusOK; - -exit: - pub.Z.p = NULL; - pub.Z.n = 0; - - mbedtls_ecp_group_free(&grp); - mbedtls_ecp_point_free(&pub); - mbedtls_mpi_free(&prv); - mbedtls_mpi_free(&secret); - - return status; -} -#endif /* NEARBY_PLATFORM_HAS_SE */ diff --git a/embedded/common/source/mbedtls/mbedtls.c b/embedded/common/source/mbedtls/mbedtls.c deleted file mode 100644 index e72b28b9..00000000 --- a/embedded/common/source/mbedtls/mbedtls.c +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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. - -// -// MBEDTLS module -// -// Purpose: Implements the cryptographic functions used by fp-provider using the -// MBEDTLS package developed by ARM. -// -// To use the package, uncomment the NEARBY_PLATFORM_USE_MBEDTLS define in -// config.mk. -// -// The following features are implemented here: -// -// nearby_platform_Sha256Start(), nearby_platform_Sha256Update(), -// nearby_platform_Sha256Finish() -// -// Implements the SHA function across and arbitrary length block. Partial -// blocks can be sent, and the resulting SHA will be over all blocks. -// -// nearby_platform_Aes128Encrypt(), nearby_platform_Aes128Decrypt() -// -// Encrypt and decrypt a block of data with a given key. -// -// Note that the required function nearby_platform_GenSec256r1Secret() is in a -// separate file, gen_secret.c. -// - -#include -#include -#include -#include /* generic interface */ -#include -#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) -#include -#endif - -#include - -static mbedtls_sha256_context sha256_ctx; - -nearby_platform_status nearby_platform_Sha256Start() { - nearby_platform_status status = kNearbyStatusError; - mbedtls_sha256_init(&sha256_ctx); - if (mbedtls_sha256_starts_ret(&sha256_ctx, 0) == 0) { - status = kNearbyStatusOK; - } else { - mbedtls_sha256_free(&sha256_ctx); - } - return status; -} - -nearby_platform_status nearby_platform_Sha256Update(const void* data, - size_t length) { - nearby_platform_status status = kNearbyStatusError; - if (mbedtls_sha256_update_ret(&sha256_ctx, (const unsigned char*)data, - length) == 0) { - status = kNearbyStatusOK; - } else { - mbedtls_sha256_free(&sha256_ctx); - } - return status; -} - -nearby_platform_status nearby_platform_Sha256Finish(uint8_t out[32]) { - nearby_platform_status status = kNearbyStatusError; - if (mbedtls_sha256_finish_ret(&sha256_ctx, out) == 0) { - status = kNearbyStatusOK; - } - mbedtls_sha256_free(&sha256_ctx); - return status; -} - -/** - * Encrypts a data block with AES128 in ECB mode. - */ -nearby_platform_status nearby_platform_Aes128Encrypt( - const uint8_t input[AES_MESSAGE_SIZE_BYTES], - uint8_t output[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]) { - nearby_platform_status status = kNearbyStatusError; - mbedtls_aes_context ctx; - mbedtls_aes_init(&ctx); - if (mbedtls_aes_setkey_enc(&ctx, key, 128) != 0) goto exit; - if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, input, output) != 0) - goto exit; - status = kNearbyStatusOK; -exit: - mbedtls_aes_free(&ctx); - return status; -} - -/** - * Decrypts a data block with AES128 in ECB mode. - */ -nearby_platform_status nearby_platform_Aes128Decrypt( - const uint8_t input[AES_MESSAGE_SIZE_BYTES], - uint8_t output[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]) { - nearby_platform_status status = kNearbyStatusError; - mbedtls_aes_context ctx; - mbedtls_aes_init(&ctx); - if (mbedtls_aes_setkey_dec(&ctx, key, 128) != 0) goto exit; - if (mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, input, output) != 0) - goto exit; - status = kNearbyStatusOK; -exit: - mbedtls_aes_free(&ctx); - return status; -} diff --git a/embedded/common/source/nearby_assert.h b/embedded/common/source/nearby_assert.h deleted file mode 100644 index 2a2b01b2..00000000 --- a/embedded/common/source/nearby_assert.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_ASSERT_H -#define NEARBY_ASSERT_H - -#include "nearby.h" -#include "nearby_platform_trace.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifdef __NEARBY_SHORT_FILE__ -#define NEARBY_ASSERT(cond) \ - do { \ - if (!(cond)) { \ - nearby_platfrom_CrashOnAssert(__NEARBY_SHORT_FILE__, __LINE__, #cond); \ - } \ - } while (0) -#else -#define NEARBY_ASSERT(cond) \ - do { \ - if (!(cond)) { \ - nearby_platfrom_CrashOnAssert(__FILE__, __LINE__, #cond); \ - } \ - } while (0) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_ASSERT_H */ diff --git a/embedded/common/source/nearby_config.h b/embedded/common/source/nearby_config.h deleted file mode 100644 index c425fc22..00000000 --- a/embedded/common/source/nearby_config.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_CONFIG_H -#define NEARBY_CONFIG_H - -// Support FP Battery Notification extension -#ifndef NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -#define NEARBY_FP_ENABLE_BATTERY_NOTIFICATION 1 -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -// Support FP Additional Data extension -#ifndef NEARBY_FP_ENABLE_ADDITIONAL_DATA -#define NEARBY_FP_ENABLE_ADDITIONAL_DATA 1 -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ - -// Personalized name max size in bytes -#define PERSONALIZED_NAME_MAX_SIZE 64 - -// Support FP Message Stream extension -#ifndef NEARBY_FP_MESSAGE_STREAM -#define NEARBY_FP_MESSAGE_STREAM 1 -#endif /* NEARBY_FP_MESSAGE_STREAM */ - -// Number of salt bytes to use in advertisements -#define NEARBY_FP_SALT_SIZE 2 - -// Does the platform have a native BLE address rotation routine? -// #define NEARBY_FP_HAVE_BLE_ADDRESS_ROTATION - -// Support Smart Audio Source Switching -// #define NEARBY_FP_ENABLE_SASS - -// The maximum size in bytes of additional data in a message in Message Stream. -// Bigger payloads will be truncated. -#define MAX_MESSAGE_STREAM_PAYLOAD_SIZE 22 - -// The maximum number of concurrent RFCOMM connections -#define NEARBY_MAX_RFCOMM_CONNECTIONS 2 - -// Support Retroactive pairing extension -#ifndef NEARBY_FP_RETROACTIVE_PAIRING -#define NEARBY_FP_RETROACTIVE_PAIRING 1 -#endif /* NEARBY_FP_RETROACTIVE_PAIRING */ - -// The maximum number of concurrent retroactive pairing process -#define NEARBY_MAX_RETROACTIVE_PAIRING 2 - -// Is this platform a BLE-only device? -#ifndef NEARBY_FP_BLE_ONLY -#define NEARBY_FP_BLE_ONLY 0 -#endif /* NEARBY_FP_BLE_ONLY */ - -// Does this device prefer BLE bonding? -#ifndef NEARBY_FP_PREFER_BLE_BONDING -#define NEARBY_FP_PREFER_BLE_BONDING 0 -#endif /* NEARBY_FP_PREFER_BLE_BONDING */ - -// Does this device prefer LE transport for FP Message Stream? -// When this feature is On, the Seeker will try to connect to the provider over -// an L2CAP channel. When this feature is Off, the Seeker connects over RFCOMM. -#ifndef NEARBY_FP_PREFER_LE_TRANSPORT -#define NEARBY_FP_PREFER_LE_TRANSPORT 0 -#endif /* NEARBY_FP_PREFER_LE_TRANSPORT */ - -// The maximum number of account keys that can be stored on the device. -#define NEARBY_MAX_ACCOUNT_KEYS 5 -#endif /* NEARBY_CONFIG_H */ diff --git a/embedded/common/source/nearby_event.h b/embedded/common/source/nearby_event.h deleted file mode 100644 index 921696ef..00000000 --- a/embedded/common/source/nearby_event.h +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_EVENT_H -#define NEARBY_EVENT_H - -#include "nearby.h" - -// Types of events that can be emitted by Nearby library -typedef enum { - // A client connected over RFCOMM to the message stream endpoint defined in - // Fast Pair specification - // Payload: |nearby_event_MessageStreamConnected| - kNearbyEventMessageStreamConnected = 0, - // An RFCOMM client disconnected - // Payload: |nearby_event_MessageStreamDisonnected| - kNearbyEventMessageStreamDisconnected, - // A client has sent a message over the message stream. Some incoming messages - // are consumed by the Nearby library, in which case the event is not emitted. - // Payload: |nearby_event_MessageStreamReceived| - kNearbyEventMessageStreamReceived -} nearby_event_Type; - -// An event emitted by Nearby library -typedef struct { - // The type of the event - nearby_event_Type event_type; - // Optional event payload. |payload| should be cast to one the structs defined - // below. - uint8_t *payload; -} nearby_event_Event; - -// Payload for |kNearbyEventMessageStreamConnected| event. -typedef struct { - // The client BT address - uint64_t peer_address; -} nearby_event_MessageStreamConnected; - -// Payload for |kNearbyEventMessageStreamDisconnected| event. -typedef struct { - // The client BT address - uint64_t peer_address; -} nearby_event_MessageStreamDisconnected; - -// Message group Bluetooth -#define MESSAGE_GROUP_BLUETOOTH 1 - -// If the device supports silence mode, the client app should send either -// ENABLE_SILENCE_MODE or DISABLE_SILENCE_MODE message to the seeker once RFCOMM -// is connected to ensure the correct state is propagated. -// Direction: Provider -> Seeker -// Handled by: Client app -#define MESSAGE_CODE_ENABLE_SILENCE_MODE 1 - -// Direction: Provider -> Seeker -// Handled by: Client app -#define MESSAGE_CODE_DISABLE_SILENCE_MODE 2 - -// Message group Companion App Event -#define MESSAGE_GROUP_COMPANION_APP_EVENT 2 - -// Direction: Provider -> Seeker -// Handled by: Client app -#define MESSAGE_CODE_LOG_BUFFER_FULL 1 - -// Message group Device Information Event -#define MESSAGE_GROUP_DEVICE_INFORMATION_EVENT 3 - -// Direction: Provider -> Seeker -// Handled by: Nearby Fast Pair library -#define MESSAGE_CODE_MODEL_ID 1 - -// Direction: Provider -> Seeker -// Handled by: Nearby Fast Pair library -#define MESSAGE_CODE_BLE_ADDRESS_UPDATED 2 - -// Direction: Provider -> Seeker -// Handled by: Nearby Fast Pair library -#define MESSAGE_CODE_BATTERY_UPDATED 3 - -// Direction: Provider -> Seeker -// Handled by: Nearby Fast Pair library -#define MESSAGE_CODE_REMAINING_BATTERY_TIME 4 - -// Direction: Seeker -> Provider -// Handled by: Client app -#define MESSAGE_CODE_ACTIVE_COMPONENT_REQUEST 5 - -// Direction: Provider -> Seeker -// Handled by: Client app -#define MESSAGE_CODE_ACTIVE_COMPONENT_RESPONSE 6 - -// Direction: Provider -> Seeker -// Handled by: Client app -#define MESSAGE_CODE_CAPABILITIES 7 - -#define MESSAGE_CODE_CAPABILITIES_COMPANION_APP_INSTALLED 0 -#define MESSAGE_CODE_CAPABILITIES_SILENCE_MODE_SUPPORTED 1 - -// Direction: Seeker -> Provider -// Handled by: Client app -#define MESSAGE_CODE_PLATFORM_TYPE 8 - -// Direction: Provider -> Seeker -// Handled by: Nearby Fast Pair library -#define MESSAGE_CODE_SESSION_NONCE 0x0A - -// Message group Device Action Event -#define MESSAGE_GROUP_DEVICE_ACTION_EVENT 4 - -// Direction: Seeker -> Provider -// Handled by: Client app -#define MESSAGE_CODE_RING 1 - -#define MESSAGE_CODE_RING_LEFT 0 -#define MESSAGE_CODE_RING_RIGHT 1 - -// Payload for |kNearbyEventMessageStreamReceived| event. See -// https://developers.google.com/nearby/fast-pair/spec#MessageStream -typedef struct { - // The peer BT address - uint64_t peer_address; - // Message group - uint8_t message_group; - // Message code - uint8_t message_code; - // If |length| is 0, then there's no additional data in the message - size_t length; - // Optional. Addtional message data - uint8_t *data; -} nearby_event_MessageStreamReceived; - -// Message group Smart Audio Source Switching -#define MESSAGE_GROUP_SASS 7 - -// Direction: Both -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: No -// ACK required: No -#define MESSAGE_CODE_SASS_GET_CAPABILITY 0x10 - -// Direction: Both -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_NOTIFY_CAPABILITY 0x11 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_SET_MULTIPOINT_STATE 0x12 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_SET_SWITCHING_PREFERENCE 0x20 - -// Direction: Both -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: No -// ACK required: No -#define MESSAGE_CODE_SASS_GET_SWITCHING_PREFERENCE 0x21 - -// Direction: Both -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_NOTIFY_SWITCHING_PREFERENCE 0x22 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_SWITCH_ACTIVE_AUDIO_SOURCE 0x30 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_SWITCH_BACK_AUDIO_SOURCE 0x31 - -// Direction: Provider -> Seeker -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: No -// ACK required: No -#define MESSAGE_CODE_SASS_NOTIFY_MULTIPOINT_SWITCH_EVENT 0x32 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: No -// ACK required: No -#define MESSAGE_CODE_SASS_GET_CONNECTION_STATUS 0x33 - -// Direction: Provider -> Seeker -// Handled by: Nearby Fast Pair library -// Encrypted: Yes -// Signed: No -// ACK required: No -#define MESSAGE_CODE_SASS_NOTIFY_CONNECTION_STATUS 0x34 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_NOTIFY_SASS_INITIATED_CONNECTION 0x40 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_IN_USE_ACCOUNT_KEY 0x41 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_SEND_CUSTOM_DATA 0x42 - -// Direction: Seeker -> Provider -// Handled by: Nearby Fast Pair library -// Encrypted: No -// Signed: Yes -// ACK required: Yes -#define MESSAGE_CODE_SASS_SET_DROP_CONNECTION_TARGET 0x43 - -#endif /* NEARBY_EVENT_H */ diff --git a/embedded/common/source/nearby_fp_library.c b/embedded/common/source/nearby_fp_library.c deleted file mode 100644 index 6c1a2a31..00000000 --- a/embedded/common/source/nearby_fp_library.c +++ /dev/null @@ -1,833 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 "nearby_fp_library.h" - -#include - -#include "nearby.h" -#include "nearby_assert.h" -#include "nearby_message_stream.h" -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -#include "nearby_platform_battery.h" -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -#include "nearby_platform_audio.h" -#include "nearby_platform_bt.h" -#include "nearby_platform_persistence.h" -#include "nearby_platform_se.h" -#include "nearby_trace.h" -#include "nearby_utils.h" - -typedef struct { - uint8_t num_keys; - nearby_platform_AccountKeyInfo key[NEARBY_MAX_ACCOUNT_KEYS]; -} AccountKeyList; - -// Advertisement header with SASS format (version 1) -#define SASS_HEADER 0x10 - -// Offset to the advertisement header -#define HEADER_OFFSET 4 - -// Offset to account data in a non-discoverable advertisement -#define ACCOUNT_KEY_DATA_OFFSET 5 - -#define LTV_HEADER_SIZE 1 -#define ACCOUNT_KEY_LIST_SIZE_BYTES sizeof(AccountKeyList) -#define SHOW_PAIRING_INDICATION_BYTE 0 -#define DONT_SHOW_PAIRING_INDICATION_BYTE 2 -#define SHOW_BATTERY_INDICATION_BYTE 0x33 -#define DONT_SHOW_BATTERY_INDICATION_BYTE 0x34 -#define BATTERY_INFO_CHARGING (1 << 7) -#define BATTERY_INFO_NOT_CHARGING 0 -// In the battery values, the highest bit indicates charging, the lower 7 are -// the battery level -#define BATTERY_LEVEL_MASK 0x7F -#define SALT_FIELD_LENGTH_AND_TYPE_BYTE ((NEARBY_FP_SALT_SIZE << 4) | 1) -#define BATTERY_INFO_SIZE_BYTES 4 -// Response for seekers that don't support BLE-only devices. -#define KEY_BASED_PAIRING_RESPONSE_FLAG 0x01 -// Response for seekers that support BLE-only devices. -#define KEY_BASED_PAIRING_EXTENDED_RESPONSE_FLAG 0x02 -#define GAP_DATA_TYPE_SERVICE_DATA_UUID 0x16 -#define FP_SERVICE_UUID 0xFE2C -#define GAP_DATA_TYPE_TX_POWER_LEVEL_UUID 0x0A -#define TX_POWER_DATA_SIZE 2 -#define SASS_HEADER_SIZE 1 - -// (type + length) + state + custom_data -#define MIN_SASS_ADERTISEMENT_SIZE 3 - -#define SASS_CONN_STATE_ON_HEAD_OFFSET 7 -#define SASS_CONN_STATE_AVAIL_OFFSET 6 -#define SASS_CONN_STATE_FOCUS_OFFSET 5 -#define SASS_CONN_STATE_AUTO_RECONNECTED_OFFSET 4 -#define SASS_CONN_STATE_MASK 0x0F - -#define MOST_RECENTLY_USED_ACCOUNT_KEY_BIT 0x01 -#define IN_USE_ACCOUNT_KEY_BIT 0x02 - -// SASS Configuration Flags -#define SASS_CF_ON_OFFSET 15 -#define SASS_CF_MULTIPOINT_CONFIGURABLE 14 -#define SASS_CF_MULTIPOINT_ON 13 -#define SASS_CF_OHD_SUPPORTED 12 -#define SASS_CF_OHD_ENABLED 11 - -#define MESSAGE_AUTHENTICATION_CODE_SIZE 8 - -#define BOOL_TO_INT(x) ((x) ? 1 : 0) - -static const uint8_t kSassRrdKey[] = {'S', 'A', 'S', 'S', '-', 'R', - 'R', 'D', '-', 'K', 'E', 'Y'}; - -static AccountKeyList account_key_list; - -static uint8_t sha_buffer[32]; - -#define RETURN_IF_ERROR(X) \ - do { \ - nearby_platform_status status = X; \ - if (kNearbyStatusOK != status) return status; \ - } while (0) - -// Returns the Length part of Length|Type field. -static int GetLtLength(uint8_t value) { return value >> 4; } - -// Returns the Type part of Length|Type field. -static int GetLtType(uint8_t value) { return value & 0x0F; } - -const uint8_t* nearby_fp_FindLtv(const uint8_t* advertisement, int type) { - size_t offset = ACCOUNT_KEY_DATA_OFFSET; - size_t advertisement_length = advertisement[0]; - while (offset < advertisement_length) { - if (type == GetLtType(advertisement[offset])) { - return advertisement + offset; - } - offset += GetLtLength(advertisement[offset]) + LTV_HEADER_SIZE; - } - return NULL; -} - -static size_t GetAccountKeyListUsedSize() { return sizeof(account_key_list); } - -// Returns true if |account_key| is present in [0..end_offset) range in acount -// key list -static bool IsAccountKeyInRange(const uint8_t* account_key, size_t end_offset) { - for (size_t i = 0; i < end_offset; i++) { - if (!memcmp(account_key, nearby_fp_GetAccountKey(i)->account_key, - ACCOUNT_KEY_SIZE_BYTES)) { - return true; - } - } - return false; -} - -size_t nearby_fp_GetAccountKeyCount() { return account_key_list.num_keys; } - -size_t nearby_fp_GetUniqueAccountKeyCount() { - size_t count = 0; - int offset = 0; - while (true) { - offset = nearby_fp_GetNextUniqueAccountKeyIndex(offset); - if (offset == -1) break; - count++; - offset++; - } - return count; -} - -int nearby_fp_GetNextUniqueAccountKeyIndex(int offset) { - while (offset < nearby_fp_GetAccountKeyCount()) { - const nearby_platform_AccountKeyInfo* account_key_info = - nearby_fp_GetAccountKey(offset); - if (IsAccountKeyInRange(account_key_info->account_key, offset)) { - offset++; - } else { - return offset; - } - } - return -1; -} - -const nearby_platform_AccountKeyInfo* nearby_fp_GetAccountKey( - unsigned key_number) { - NEARBY_ASSERT(key_number < nearby_fp_GetAccountKeyCount()); - return &account_key_list.key[key_number]; -} - -void nearby_fp_MarkAccountKeyAsActive(unsigned key_number) { - NEARBY_ASSERT(key_number < nearby_fp_GetAccountKeyCount()); - if (key_number == 0) return; - // Move the key to the top of the list - nearby_platform_AccountKeyInfo tmp = account_key_list.key[key_number]; - for (unsigned i = key_number; i > 0; i--) { - account_key_list.key[i] = account_key_list.key[i - 1]; - } - account_key_list.key[0] = tmp; -} - -void nearby_fp_CopyAccountKey(nearby_platform_AccountKeyInfo* dest, - unsigned key_number) { - NEARBY_ASSERT(key_number < nearby_fp_GetAccountKeyCount()); - *dest = account_key_list.key[key_number]; -} - -static unsigned combineNibbles(unsigned high, unsigned low) { - return ((high << 4) & 0xF0) | (low & 0x0F); -} - -// Returns |a| == |b| -static bool AccountKeyInfoEquals(const nearby_platform_AccountKeyInfo* a, - const nearby_platform_AccountKeyInfo* b) { - return a == b || - ( -#ifdef NEARBY_FP_ENABLE_SASS - a->peer_address == b->peer_address && -#endif /* NEARBY_FP_ENABLE_SASS */ - !memcmp(a->account_key, b->account_key, ACCOUNT_KEY_SIZE_BYTES)); -} - -void nearby_fp_AddAccountKey(const nearby_platform_AccountKeyInfo* key) { - // Find if the key is already on the list - unsigned i; - size_t key_count; - key_count = nearby_fp_GetAccountKeyCount(); - for (i = 0; i < key_count; i++) { - if (AccountKeyInfoEquals(key, nearby_fp_GetAccountKey(i))) { - nearby_fp_MarkAccountKeyAsActive(i); - return; - } - } - // Insert `key` at the list top. If the list is full, the last key will fall - // off the edge - size_t keys_to_copy = key_count < NEARBY_MAX_ACCOUNT_KEYS - ? key_count - : NEARBY_MAX_ACCOUNT_KEYS - 1; - for (i = keys_to_copy; i > 0; i--) { - account_key_list.key[i] = account_key_list.key[i - 1]; - } - account_key_list.key[0] = *key; - if (key_count < NEARBY_MAX_ACCOUNT_KEYS) { - account_key_list.num_keys++; - } -} -size_t nearby_fp_CreateDiscoverableAdvertisement(uint8_t* output, - size_t length) { - NEARBY_ASSERT(length >= DISCOVERABLE_ADV_SIZE_BYTES); - - size_t i = 0; - - // data size - output[i++] = 1 + FP_SERVICE_UUID_SIZE + FP_MODEL_ID_SIZE; - - // data type service - output[i++] = GAP_DATA_TYPE_SERVICE_DATA_UUID; - - // service data uuid - nearby_utils_CopyLittleEndian(output + i, FP_SERVICE_UUID, - FP_SERVICE_UUID_SIZE); - i += FP_SERVICE_UUID_SIZE; - - // service data - uint32_t model = nearby_platform_GetModelId(); - nearby_utils_CopyBigEndian(output + i, model, FP_MODEL_ID_SIZE); - i += FP_MODEL_ID_SIZE; - - return i; -} - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -void SerializeBatteryInfo(uint8_t* output, - const nearby_platform_BatteryInfo* battery_info) { - uint8_t charging = battery_info->is_charging ? BATTERY_INFO_CHARGING - : BATTERY_INFO_NOT_CHARGING; - output[0] = - charging | (battery_info->left_bud_battery_level & BATTERY_LEVEL_MASK); - output[1] = - charging | (battery_info->right_bud_battery_level & BATTERY_LEVEL_MASK); - output[2] = charging | - (battery_info->charging_case_battery_level & BATTERY_LEVEL_MASK); -} -static void AddBatteryInfo(uint8_t* output, size_t length, - bool show_ui_indicator, - const nearby_platform_BatteryInfo* battery_info) { - NEARBY_ASSERT(length >= BATTERY_INFO_SIZE_BYTES); - output[0] = show_ui_indicator ? SHOW_BATTERY_INDICATION_BYTE - : DONT_SHOW_BATTERY_INDICATION_BYTE; - SerializeBatteryInfo(output + 1, battery_info); -} - -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -static size_t CreateNondiscoverableAdvertisement( - uint8_t* output, size_t length, bool show_pairing_indicator -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION - , - bool show_battery_indicator, const nearby_platform_BatteryInfo* battery_info -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ -) { - NEARBY_TRACE(VERBOSE, "nearby_fp_CreateNondiscoverableAdvertisement"); - const unsigned kHeaderSize = FP_SERVICE_UUID_SIZE + 2; - NEARBY_ASSERT(length >= kHeaderSize); - - unsigned i = 1; - uint8_t salt[NEARBY_FP_SALT_SIZE]; - - // service data UUID - output[i++] = GAP_DATA_TYPE_SERVICE_DATA_UUID; - - // service uuid - nearby_utils_CopyLittleEndian(output + i, FP_SERVICE_UUID, - FP_SERVICE_UUID_SIZE); - i += FP_SERVICE_UUID_SIZE; - - // service data - for (int si = 0; si < NEARBY_FP_SALT_SIZE; si++) - salt[si] = nearby_platform_Rand(); - size_t n = nearby_fp_GetUniqueAccountKeyCount(); - if (n == 0) { - const unsigned kMessageSize = 2; - NEARBY_ASSERT(length >= i + kMessageSize); - output[i++] = 0x00; - output[i++] = 0x00; - } else { - const unsigned kFlagFilterAndSaltSize = 3 + NEARBY_FP_SALT_SIZE; - const size_t s = (6 * n + 15) / 5; - const size_t kAccountKeyDataSize = s + kFlagFilterAndSaltSize; - NEARBY_ASSERT(length >= i + kAccountKeyDataSize); -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION - // We need to add the battery info first because it's used as salt - if (battery_info != NULL) { - uint8_t battery_chunk_offset = i + kAccountKeyDataSize; - uint8_t* battery_chunk = output + battery_chunk_offset; - AddBatteryInfo(battery_chunk, length - battery_chunk_offset, - show_battery_indicator, battery_info); - } -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - // flags - output[i++] = 0; - // filter length and type - output[i++] = combineNibbles(s, show_pairing_indicator - ? SHOW_PAIRING_INDICATION_BYTE - : DONT_SHOW_PAIRING_INDICATION_BYTE); - memset(output + i, 0, s); - i += s; - output[i++] = SALT_FIELD_LENGTH_AND_TYPE_BYTE; - for (int si = 0; si < NEARBY_FP_SALT_SIZE; si++) output[i++] = salt[si]; -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION - if (battery_info != NULL) { - i += BATTERY_INFO_SIZE_BYTES; - } -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - } - - // service data size - output[0] = i - 1; - - return i; -} - -size_t nearby_fp_CreateNondiscoverableAdvertisement( - uint8_t* output, size_t length, bool show_pairing_indicator) { -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION - return CreateNondiscoverableAdvertisement( - output, length, show_pairing_indicator, false, NULL); -#else - return CreateNondiscoverableAdvertisement(output, length, - show_pairing_indicator); -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ -} - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -// |battery_info| can be NULL -size_t nearby_fp_CreateNondiscoverableAdvertisementWithBattery( - uint8_t* output, size_t length, bool show_pairing_indicator, - - bool show_battery_indicator, - const nearby_platform_BatteryInfo* battery_info) { - return CreateNondiscoverableAdvertisement( - output, length, show_pairing_indicator, show_battery_indicator, - battery_info); -} -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -static const uint8_t* FindBatteryInfoLt(const uint8_t* advertisement) { - const uint8_t* battery_info = nearby_fp_FindLtv( - advertisement, BATTERY_INFO_WITH_UI_INDICATION_FIELD_TYPE); - if (battery_info == NULL) { - battery_info = nearby_fp_FindLtv( - advertisement, BATTERY_INFO_WITHOUT_UI_INDICATION_FIELD_TYPE); - } - return battery_info; -} - -size_t nearby_fp_SetBloomFilter(uint8_t* advertisement, bool use_sass_format, - const uint8_t* in_use_key) { - unsigned key_offset = 0; - if (advertisement[ACCOUNT_KEY_DATA_OFFSET] == 0) { - NEARBY_TRACE(INFO, "Empty account key filter"); - return 0; - } - // Salt is mandatory and is included in the calculation without the LT header - const uint8_t* salt_field = nearby_fp_FindLtv(advertisement, SALT_FIELD_TYPE); - NEARBY_ASSERT(salt_field != NULL); - const uint8_t* salt = salt_field + LTV_HEADER_SIZE; - int salt_length = GetLtLength(*salt_field); - // Battery info is optional and is included in the calculation with the LT - // header - const uint8_t* battery_info_field = FindBatteryInfoLt(advertisement); - int battery_info_field_length = - battery_info_field != NULL - ? GetLtLength(*battery_info_field) + LTV_HEADER_SIZE - : 0; - // Random resolvable field is optional and is included in the calculation with - // the LT header - const uint8_t* random_resolvable_field = - nearby_fp_FindLtv(advertisement, RANDOM_RESOLVABLE_FIELD_TYPE); - int random_resolvable_field_length = - random_resolvable_field != NULL - ? GetLtLength(*random_resolvable_field) + LTV_HEADER_SIZE - : 0; - const size_t n = nearby_fp_GetUniqueAccountKeyCount(); - const size_t s = (6 * n + 15) / 5; - NEARBY_ASSERT(s == GetLtLength(advertisement[ACCOUNT_KEY_DATA_OFFSET])); - uint8_t* output = advertisement + ACCOUNT_KEY_DATA_OFFSET + LTV_HEADER_SIZE; - memset(output, 0, s); - for (size_t k = 0; k < n; k++) { - key_offset = nearby_fp_GetNextUniqueAccountKeyIndex(key_offset); - NEARBY_ASSERT(key_offset >= 0); - const uint8_t* key = nearby_fp_GetAccountKey(key_offset)->account_key; - uint8_t flags = key[0]; - if (use_sass_format) { - if (in_use_key != NULL) { - if (!memcmp(key, in_use_key, ACCOUNT_KEY_SIZE_BYTES)) { - flags |= IN_USE_ACCOUNT_KEY_BIT; - } - } else if (k == 0) { - // The first key is the most recently used one - flags |= MOST_RECENTLY_USED_ACCOUNT_KEY_BIT; - } - } - key_offset++; - nearby_platform_Sha256Start(); - nearby_platform_Sha256Update(&flags, sizeof(flags)); - nearby_platform_Sha256Update(key + sizeof(flags), - ACCOUNT_KEY_SIZE_BYTES - sizeof(flags)); - nearby_platform_Sha256Update(salt, salt_length); - nearby_platform_Sha256Update(battery_info_field, battery_info_field_length); - nearby_platform_Sha256Update(random_resolvable_field, - random_resolvable_field_length); - nearby_platform_Sha256Finish(sha_buffer); - for (unsigned j = 0; j < 8; j++) { - uint32_t x = nearby_utils_GetBigEndian32(sha_buffer + 4 * j); - uint32_t m = x % (s * 8); - output[m / 8] |= (1 << (m % 8)); - } - } - if (use_sass_format) { - advertisement[HEADER_OFFSET] = SASS_HEADER; - } - return s; -} - -size_t nearby_fp_AppendTxPower(uint8_t* advertisement, size_t length, - int8_t tx_power) { - size_t offset = 0; - - NEARBY_ASSERT(length >= 1 + TX_POWER_DATA_SIZE); - // tx power level data size - advertisement[offset++] = TX_POWER_DATA_SIZE; - // tx power level UUID - advertisement[offset++] = GAP_DATA_TYPE_TX_POWER_LEVEL_UUID; - // tx power level - advertisement[offset++] = tx_power; - - return offset; -} - -nearby_platform_status nearby_fp_LoadAccountKeys() { - size_t length = sizeof(account_key_list); - memset(&account_key_list, 0, length); - return nearby_platform_LoadValue(kStoredKeyAccountKeyList, - (uint8_t*)&account_key_list, &length); -} - -nearby_platform_status nearby_fp_SaveAccountKeys() { - return nearby_platform_SaveValue(kStoredKeyAccountKeyList, - (uint8_t*)&account_key_list, - GetAccountKeyListUsedSize()); -} - -nearby_platform_status nearby_fp_GattReadModelId(uint8_t* output, - size_t* length) { - NEARBY_ASSERT(*length >= FP_MODEL_ID_SIZE); - uint32_t model = nearby_platform_GetModelId(); - nearby_utils_CopyBigEndian(output, model, FP_MODEL_ID_SIZE); - *length = FP_MODEL_ID_SIZE; - return kNearbyStatusOK; -} - -nearby_platform_status nearby_fp_CreateSharedSecret( - const uint8_t remote_public_key[64], - uint8_t output[ACCOUNT_KEY_SIZE_BYTES]) { - nearby_platform_status status; - uint8_t secret[32]; - uint8_t hash[32]; - status = nearby_platform_GenSec256r1Secret(remote_public_key, secret); - if (status != kNearbyStatusOK) return status; - - status = nearby_fp_Sha256(hash, secret, sizeof(secret)); - if (status != kNearbyStatusOK) return status; - - memcpy(output, hash, ACCOUNT_KEY_SIZE_BYTES); - return status; -} - -nearby_platform_status nearby_fp_CreateRawKeybasedPairingResponse( - uint8_t output[AES_MESSAGE_SIZE_BYTES], bool extended_response) { - int i = 0; - uint64_t secondary_address = 0; - if (extended_response) { - secondary_address = nearby_platform_GetSecondaryPublicAddress(); - output[i++] = KEY_BASED_PAIRING_EXTENDED_RESPONSE_FLAG; - uint8_t flags = 0; -#if NEARBY_FP_BLE_ONLY - flags |= 0x80; -#endif /* NEARBY_FP_BLE_ONLY */ -#if NEARBY_FP_PREFER_BLE_BONDING - flags |= 0x40; -#endif /* NEARBY_FP_PREFER_BLE_BONDING */ -#if NEARBY_FP_PREFER_LE_TRANSPORT - flags |= 0x20; -#endif /* NEARBY_FP_PREFER_LE_TRANSPORT */ - output[i++] = flags; - // Number of the Provider’s addresses. The number is either 1 or 2. - output[i++] = secondary_address != 0 ? 2 : 1; - } else { - output[i++] = KEY_BASED_PAIRING_RESPONSE_FLAG; - } - nearby_utils_CopyBigEndian(&output[i], nearby_platform_GetPublicAddress(), - BT_ADDRESS_LENGTH); - i += BT_ADDRESS_LENGTH; - if (secondary_address != 0) { - nearby_utils_CopyBigEndian(&output[i], secondary_address, - BT_ADDRESS_LENGTH); - i += BT_ADDRESS_LENGTH; - } - for (; i < AES_MESSAGE_SIZE_BYTES; i++) { - output[i] = nearby_platform_Rand(); - } - return kNearbyStatusOK; -} - -#define OPAD 0x5C -#define IPAD 0x36 -#define NONCE_SIZE 8 - -static void PadKey(uint8_t output[HMAC_SHA256_KEY_SIZE], const uint8_t* key, - size_t key_length, uint8_t pad) { - size_t i; - for (i = 0; i < key_length; i++) { - *output++ = *key++ ^ pad; - } - memset(output, pad, HMAC_SHA256_KEY_SIZE - key_length); -} - -static nearby_platform_status HmacSha256(uint8_t out[SHA256_KEY_SIZE], - uint8_t hmac_key[HMAC_SHA256_KEY_SIZE], - const uint8_t* data, - size_t data_length) { - RETURN_IF_ERROR(nearby_platform_Sha256Start()); - RETURN_IF_ERROR(nearby_platform_Sha256Update(hmac_key, HMAC_SHA256_KEY_SIZE)); - RETURN_IF_ERROR(nearby_platform_Sha256Update(data, data_length)); - return nearby_platform_Sha256Finish(out); -} - -static nearby_platform_status HmacSha256WithNonce( - uint8_t out[32], uint8_t hmac_key[HMAC_SHA256_KEY_SIZE], - const uint8_t session_nonce[SESSION_NONCE_SIZE], - const uint8_t message_nonce[SESSION_NONCE_SIZE], const uint8_t* data, - size_t data_length) { - RETURN_IF_ERROR(nearby_platform_Sha256Start()); - RETURN_IF_ERROR(nearby_platform_Sha256Update(hmac_key, HMAC_SHA256_KEY_SIZE)); - RETURN_IF_ERROR( - nearby_platform_Sha256Update(session_nonce, SESSION_NONCE_SIZE)); - RETURN_IF_ERROR( - nearby_platform_Sha256Update(message_nonce, SESSION_NONCE_SIZE)); - RETURN_IF_ERROR(nearby_platform_Sha256Update(data, data_length)); - RETURN_IF_ERROR(nearby_platform_Sha256Finish(out)); - return kNearbyStatusOK; -} - -nearby_platform_status nearby_fp_HmacSha256Start( - nearby_fp_HmacSha256Context* context, const uint8_t* key, - size_t key_length) { - // out = HASH(Key XOR ipad, data) - PadKey(context->hmac_key, key, key_length, IPAD); - RETURN_IF_ERROR(nearby_platform_Sha256Start()); - return nearby_platform_Sha256Update(context->hmac_key, HMAC_SHA256_KEY_SIZE); -} - -nearby_platform_status nearby_fp_HmacSha256Update(const uint8_t* data, - size_t data_length) { - return nearby_platform_Sha256Update(data, data_length); -} - -nearby_platform_status nearby_fp_HmacSha256Finish( - nearby_fp_HmacSha256Context* context, const uint8_t* key, - size_t key_length) { - RETURN_IF_ERROR(nearby_platform_Sha256Finish(context->hash)); - // out = HASH(Key XOR opad, out) - PadKey(context->hmac_key, key, key_length, OPAD); - return HmacSha256(context->hash, context->hmac_key, context->hash, - SHA256_KEY_SIZE); -} - -nearby_platform_status nearby_fp_HmacSha256(uint8_t out[SHA256_KEY_SIZE], - const uint8_t* key, - size_t key_length, - const uint8_t* data, - size_t data_length) { - uint8_t hmac_key[HMAC_SHA256_KEY_SIZE]; - // out = HASH(Key XOR ipad, data) - PadKey(hmac_key, key, key_length, IPAD); - RETURN_IF_ERROR(HmacSha256(out, hmac_key, data, data_length)); - // out = HASH(Key XOR opad, out) - PadKey(hmac_key, key, key_length, OPAD); - return HmacSha256(out, hmac_key, out, SHA256_KEY_SIZE); -} - -nearby_platform_status nearby_fp_HkdfExtractSha256(uint8_t out[SHA256_KEY_SIZE], - const uint8_t* salt, - size_t salt_length, - const uint8_t* ikm, - size_t ikm_length) { - return nearby_fp_HmacSha256(out, salt, salt_length, ikm, ikm_length); -} - -nearby_platform_status nearby_fp_HkdfExpandSha256( - uint8_t* out, size_t out_length, const uint8_t* prk, size_t prk_length, - const uint8_t* info, size_t info_length) { - nearby_fp_HmacSha256Context context; - size_t offset = 0; - uint8_t chunk_number = 1; - while (offset < out_length) { - RETURN_IF_ERROR(nearby_fp_HmacSha256Start(&context, prk, prk_length)); - if (offset != 0) { - RETURN_IF_ERROR( - nearby_fp_HmacSha256Update(context.hash, SHA256_KEY_SIZE)); - } - RETURN_IF_ERROR(nearby_fp_HmacSha256Update(info, info_length)); - RETURN_IF_ERROR( - nearby_fp_HmacSha256Update(&chunk_number, sizeof(chunk_number))); - RETURN_IF_ERROR(nearby_fp_HmacSha256Finish(&context, prk, prk_length)); - size_t space_left = out_length - offset; - size_t bytes_to_copy = - space_left < SHA256_KEY_SIZE ? space_left : SHA256_KEY_SIZE; - memcpy(out + offset, context.hash, bytes_to_copy); - offset += bytes_to_copy; - ++chunk_number; - } - return kNearbyStatusOK; -} - -static nearby_platform_status GetRrdKey( - uint8_t out[AES_MESSAGE_SIZE_BYTES], - const uint8_t account_key[ACCOUNT_KEY_SIZE_BYTES]) { - uint8_t prk[SHA256_KEY_SIZE]; - RETURN_IF_ERROR(nearby_fp_HkdfExtractSha256(prk, NULL, 0, account_key, - ACCOUNT_KEY_SIZE_BYTES)); - return nearby_fp_HkdfExpandSha256(out, AES_MESSAGE_SIZE_BYTES, prk, - sizeof(prk), kSassRrdKey, - sizeof(kSassRrdKey)); -} - -nearby_platform_status nearby_fp_AesCtr( - uint8_t* message, size_t message_length, - const uint8_t key[AES_MESSAGE_SIZE_BYTES]) { - uint8_t key_stream[AES_MESSAGE_SIZE_BYTES]; - uint8_t iv[AES_MESSAGE_SIZE_BYTES]; - size_t offset = NONCE_SIZE; - memset(iv, 0, AES_MESSAGE_SIZE_BYTES - NONCE_SIZE); - memcpy(iv + AES_MESSAGE_SIZE_BYTES - NONCE_SIZE, message, NONCE_SIZE); - - while (offset < message_length) { - unsigned i; - unsigned bytes_left = message_length - offset; - RETURN_IF_ERROR(nearby_platform_Aes128Encrypt(iv, key_stream, key)); - for (i = 0; i < bytes_left && i < sizeof(key_stream); i++) { - message[offset++] ^= key_stream[i]; - } - iv[0]++; - } - return kNearbyStatusOK; -} - -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA -#define ADDITIONAL_DATA_SHA_SIZE 8 -nearby_platform_status nearby_fp_DecodeAdditionalData( - uint8_t* data, size_t length, const uint8_t key[ACCOUNT_KEY_SIZE_BYTES]) { - NEARBY_ASSERT(length > ADDITIONAL_DATA_SHA_SIZE + NONCE_SIZE); - uint8_t sha[32]; - RETURN_IF_ERROR(nearby_fp_HmacSha256(sha, key, ACCOUNT_KEY_SIZE_BYTES, - data + ADDITIONAL_DATA_SHA_SIZE, - length - ADDITIONAL_DATA_SHA_SIZE)); - if (memcmp(sha, data, ADDITIONAL_DATA_SHA_SIZE) != 0) { - NEARBY_TRACE(WARNING, "Additional Data SHA check failed"); - NEARBY_TRACE(WARNING, "SHA: %s", - nearby_utils_ArrayToString(sha, sizeof(sha))); - NEARBY_TRACE( - WARNING, "key: %s", - nearby_utils_ArrayToString(key, sizeof(ACCOUNT_KEY_SIZE_BYTES))); - NEARBY_TRACE(WARNING, "data: %s", nearby_utils_ArrayToString(data, length)); - return kNearbyStatusError; - } - return nearby_fp_AesCtr(data + ADDITIONAL_DATA_SHA_SIZE, - length - ADDITIONAL_DATA_SHA_SIZE, key); -} - -nearby_platform_status nearby_fp_EncodeAdditionalData( - uint8_t* data, size_t length, const uint8_t key[ACCOUNT_KEY_SIZE_BYTES]) { - NEARBY_ASSERT(length >= ADDITIONAL_DATA_SHA_SIZE + NONCE_SIZE); - uint8_t sha[32]; - int i; - for (i = 0; i < NONCE_SIZE; i++) { - data[ADDITIONAL_DATA_SHA_SIZE + i] = nearby_platform_Rand(); - } - RETURN_IF_ERROR(nearby_fp_AesCtr(data + ADDITIONAL_DATA_SHA_SIZE, - length - ADDITIONAL_DATA_SHA_SIZE, key)); - RETURN_IF_ERROR(nearby_fp_HmacSha256(sha, key, ACCOUNT_KEY_SIZE_BYTES, - data + ADDITIONAL_DATA_SHA_SIZE, - length - ADDITIONAL_DATA_SHA_SIZE)); - memcpy(data, sha, ADDITIONAL_DATA_SHA_SIZE); - return kNearbyStatusOK; -} -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ - -// Computes sha256 sum. -nearby_platform_status nearby_fp_Sha256(uint8_t out[32], const void* data, - size_t length) { - nearby_platform_status status = nearby_platform_Sha256Start(); - if (status == kNearbyStatusOK) { - status = nearby_platform_Sha256Update(data, length); - if (status == kNearbyStatusOK) { - status = nearby_platform_Sha256Finish(out); - } - } - return status; -} - -uint8_t nearby_fp_GetSassConnectionState() { - return (BOOL_TO_INT(nearby_platform_OnHead()) - << SASS_CONN_STATE_ON_HEAD_OFFSET) | - (BOOL_TO_INT(nearby_platform_CanAcceptConnection()) - << SASS_CONN_STATE_AVAIL_OFFSET) | - (BOOL_TO_INT(nearby_platform_InFocusMode()) - << SASS_CONN_STATE_FOCUS_OFFSET) | - (BOOL_TO_INT(nearby_platform_AutoReconnected()) - << SASS_CONN_STATE_AUTO_RECONNECTED_OFFSET) | - (nearby_platform_GetAudioConnectionState() & SASS_CONN_STATE_MASK); -} - -size_t nearby_fp_GenerateSassAdvertisement( - uint8_t* advertisement, size_t length, uint8_t connection_state, - uint8_t custom_data, const uint8_t* devices_bitmap, size_t bitmap_length) { - size_t advert_size = MIN_SASS_ADERTISEMENT_SIZE + bitmap_length; - NEARBY_ASSERT(length >= advert_size); - size_t offset = 0; - advertisement[offset++] = combineNibbles(advert_size - SASS_HEADER_SIZE, - SASS_ADVERTISEMENT_FIELD_TYPE); - advertisement[offset++] = connection_state; - advertisement[offset++] = custom_data; - memcpy(advertisement + offset, devices_bitmap, bitmap_length); - return advert_size; -} - -nearby_platform_status nearby_fp_EncryptRandomResolvableField( - uint8_t* data, size_t length, const uint8_t key[AES_MESSAGE_SIZE_BYTES], - const uint8_t* salt_field) { - NEARBY_ASSERT(length <= AES_MESSAGE_SIZE_BYTES + RRF_HEADER_SIZE); - uint8_t iv[AES_MESSAGE_SIZE_BYTES]; - uint8_t rrd_key[AES_MESSAGE_SIZE_BYTES]; - memset(iv, 0, sizeof(iv)); - if (salt_field != NULL) { - int salt_length = GetLtLength(salt_field[0]); - memcpy(iv, salt_field + LTV_HEADER_SIZE, salt_length); - } - RETURN_IF_ERROR(GetRrdKey(rrd_key, key)); - RETURN_IF_ERROR(nearby_platform_Aes128Encrypt(iv, iv, rrd_key)); - data[0] = - combineNibbles(length - RRF_HEADER_SIZE, RANDOM_RESOLVABLE_FIELD_TYPE); - for (size_t i = RRF_HEADER_SIZE; i < length; i++) { - data[i] ^= iv[i - RRF_HEADER_SIZE]; - } - return kNearbyStatusOK; -} - -nearby_platform_status nearby_fp_AesEncryptIv( - uint8_t* data, size_t length, uint8_t iv[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]) { - NEARBY_ASSERT(length <= AES_MESSAGE_SIZE_BYTES); - RETURN_IF_ERROR(nearby_platform_Aes128Encrypt(iv, iv, key)); - for (size_t i = 0; i < length; i++) { - data[i] ^= iv[i]; - } - return kNearbyStatusOK; -} - -uint16_t nearby_fp_GetSassCapabilityFlags() { - return (BOOL_TO_INT(nearby_platform_IsSassOn()) << SASS_CF_ON_OFFSET) | - (BOOL_TO_INT(nearby_platform_IsMultipointConfigurable()) - << SASS_CF_MULTIPOINT_CONFIGURABLE) | - (BOOL_TO_INT(nearby_platform_IsMultipointOn()) - << SASS_CF_MULTIPOINT_ON) | - (BOOL_TO_INT(nearby_platform_IsOnHeadDetectionSupported()) - << SASS_CF_OHD_SUPPORTED) | - (BOOL_TO_INT(nearby_platform_IsOnHeadDetectionEnabled()) - << SASS_CF_OHD_ENABLED); -} - -nearby_platform_status nearby_fp_VerifyMessageAuthenticationCode( - const uint8_t* message, size_t length, - const uint8_t key[ACCOUNT_KEY_SIZE_BYTES], - const uint8_t session_nonce[SESSION_NONCE_SIZE]) { - if (length <= SESSION_NONCE_SIZE - MESSAGE_AUTHENTICATION_CODE_SIZE) { - return kNearbyStatusInvalidInput; - } - size_t data_length = - length - SESSION_NONCE_SIZE - MESSAGE_AUTHENTICATION_CODE_SIZE; - const uint8_t* message_nonce = message + data_length; - uint8_t hmac_key[HMAC_SHA256_KEY_SIZE]; - uint8_t out[32]; - // out = HASH(Key XOR ipad, session nonce + message nonce + data) - PadKey(hmac_key, key, ACCOUNT_KEY_SIZE_BYTES, IPAD); - RETURN_IF_ERROR(HmacSha256WithNonce(out, hmac_key, session_nonce, - message_nonce, message, data_length)); - // out = HASH(Key XOR opad, out) - PadKey(hmac_key, key, ACCOUNT_KEY_SIZE_BYTES, OPAD); - RETURN_IF_ERROR(HmacSha256(out, hmac_key, out, 32)); - const uint8_t* mac = message + data_length + SESSION_NONCE_SIZE; - if (memcmp(out, mac, MESSAGE_AUTHENTICATION_CODE_SIZE)) { - NEARBY_TRACE(INFO, - "Expected MAC " - "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x", - out[0], out[1], out[2], out[3], out[4], out[5], out[6], - out[7]); - return kNearbyStatusInvalidInput; - } else { - return kNearbyStatusOK; - } -} diff --git a/embedded/common/source/nearby_fp_library.h b/embedded/common/source/nearby_fp_library.h deleted file mode 100644 index 6e44a930..00000000 --- a/embedded/common/source/nearby_fp_library.h +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_FP_LIBRARY_H -#define NEARBY_FP_LIBRARY_H - -// clang-format off -#include "nearby_config.h" -// clang-format on - -#include "nearby.h" -#include "nearby_message_stream.h" -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -#include "nearby_platform_battery.h" -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#define BT_ADDRESS_LENGTH 6 -#define DISCOVERABLE_ADV_SIZE_BYTES 10 -#ifdef NEARBY_FP_ENABLE_SASS -// Sufficent for 5 account keys, battery notification and SASS info -#define NON_DISCOVERABLE_ADV_SIZE_BYTES 32 -#else -// Sufficent for 5 account keys and battery notification -#define NON_DISCOVERABLE_ADV_SIZE_BYTES 25 -#endif /* NEARBY_FP_ENABLE_SASS */ - -#define ADDITIONAL_DATA_HEADER_SIZE 16 -#define HMAC_SHA256_KEY_SIZE 64 -#define SHA256_KEY_SIZE 32 - -// Random Resolvable Field header size -#define RRF_HEADER_SIZE 1 - -// Field types in the non-discoverable advertisement -#define SALT_FIELD_TYPE 1 -#define BATTERY_INFO_WITH_UI_INDICATION_FIELD_TYPE 3 -#define BATTERY_INFO_WITHOUT_UI_INDICATION_FIELD_TYPE 4 -#define SASS_ADVERTISEMENT_FIELD_TYPE 5 -#define RANDOM_RESOLVABLE_FIELD_TYPE 6 - -// Creates advertisement with the Model Id. Returns the number of bytes -// written to |output|. -// -// output - Advertisement data output buffer. -// length - Length of output buffer. -size_t nearby_fp_CreateDiscoverableAdvertisement(uint8_t* output, - size_t length); - -// Creates advertisement with Account Key Data. Returns the number of bytes -// written to |output|. -// -// output - Advertisement data output buffer. -// length - Length of data output buffer. -// show_ui_indicator - Ask seeker to show UI indication. -size_t nearby_fp_CreateNondiscoverableAdvertisement( - uint8_t* output, size_t length, bool show_pairing_indicator); - -#if NEARBY_FP_ENABLE_BATTERY_NOTIFICATION -void SerializeBatteryInfo(uint8_t* output, - const nearby_platform_BatteryInfo* battery_info); - -// Creates advertisement with Account Key Data and optionally battery info. -// |battery_info| can be NULL. Returns the number of bytes written to |output|. -// -// output - Advertisement data output buffer. -// length - Length of output buffer. -// show_ui_indicator - Ask seeker to show UI indication. -// show_battery_indicator - Ask seeker to show battery indicator -// battery_info - Battery status data structure. -size_t nearby_fp_CreateNondiscoverableAdvertisementWithBattery( - uint8_t* output, size_t length, bool show_pairing_indicator, - bool show_battery_indicator, - const nearby_platform_BatteryInfo* battery_info); -#endif /* NEARBY_FP_ENABLE_BATTERY_NOTIFICATION */ - -// Appends TX power stanza to the advertisement. |Advertisement| should point -// past the end of advertisement created with one of the 'Create*' functions. -// -// advertisement - Pointer to end of advertising data. -// length - Remaining length of advertising data. -// power - Power level. -size_t nearby_fp_AppendTxPower(uint8_t* advertisement, size_t length, - int8_t tx_power); - -// Loads account keys from NV storage. -nearby_platform_status nearby_fp_LoadAccountKeys(); -// Saves account keys to NV storage. -nearby_platform_status nearby_fp_SaveAccountKeys(); - -// Gets Specific key by number to buffer -// -// dest - Buffer for key fetched. -// key_number - Number of key to fetch. -void nearby_fp_CopyAccountKey(nearby_platform_AccountKeyInfo* dest, - unsigned key_number); - -// Gets number of active keys. -size_t nearby_fp_GetAccountKeyCount(); - -// Gets the number of unique account keys. Account keys are duplicated when two -// or more seekers share an account key -size_t nearby_fp_GetUniqueAccountKeyCount(); - -// Returns the index of the next unique account key in [offset..number of keys] -// range, that is a key that wasn't already seen in [0..offset -1] range. -// Returns -1 if not found. -int nearby_fp_GetNextUniqueAccountKeyIndex(int offset); - -// Gets pointer to given key by ordinal number. -// -// key_number - Ordinal number of key to return. -const nearby_platform_AccountKeyInfo* nearby_fp_GetAccountKey( - unsigned key_number); - -// Marks account key as active by moving it to the top of the key list. -// -// key_number - Original number of key to mark active. -void nearby_fp_MarkAccountKeyAsActive(unsigned key_number); - -// Adds key to key list. Inserts key to top of list. -// -// key - Buffer containing key to insert. -void nearby_fp_AddAccountKey(const nearby_platform_AccountKeyInfo* key); - -// Computes the account bloom filter and stores it in the Account Key Filter -// field in the advertisement. Returns the bloom filter size. -// -// `advertisement` is a non-discoverable FP advertisement. It must contain an -// LTV field for Account Key Filter, where the LT header is already set but the -// contents may be unitialized. It must contain an LTV with salt. Battery Info -// field and Random Resolvable field are used in the bloom filter calculation if -// present in the advertisement, When `use_sass_format` is set, the bloom filter -// defined by SASS will be used. -size_t nearby_fp_SetBloomFilter(uint8_t* advertisement, bool use_sass_format, - const uint8_t* in_use_key); - -// Gets fast pair model ID -// -// output - Buffer to hold model ID. -// length - On input, contains the length of the buffer. -// On output, returns the length of the model ID returned. -nearby_platform_status nearby_fp_GattReadModelId(uint8_t* output, - size_t* length); -// Creates shared secret from remote public key. -// -// remote_public_key - 512 bit peer public key. -// output - Buffer that returns the shared secret. -nearby_platform_status nearby_fp_CreateSharedSecret( - const uint8_t remote_public_key[64], - uint8_t output[ACCOUNT_KEY_SIZE_BYTES]); - -// Creates raw key based paring response. -// -// output - Buffer returning the pairing response. -nearby_platform_status nearby_fp_CreateRawKeybasedPairingResponse( - uint8_t output[AES_MESSAGE_SIZE_BYTES], bool extended_response); - -// Context for calculating HMAC-SHA256 hash -typedef struct { - // The resulting hash after calling `nearby_fp_HmacSha256Finish` - uint8_t hash[SHA256_KEY_SIZE]; - uint8_t hmac_key[HMAC_SHA256_KEY_SIZE]; -} nearby_fp_HmacSha256Context; - -// Starts calculating HMAC-SHA156 hash incrementally. Only one hash calculation -// can be running at a time. -// -// context - Uninitalized context. -// key - Input key to calculate hash. -// key_length - Length of key. -nearby_platform_status nearby_fp_HmacSha256Start( - nearby_fp_HmacSha256Context* context, const uint8_t* key, - size_t key_length); - -// Adds data to the hash. -// -// data - Data to calculate hash. -// data_length - Data length. -nearby_platform_status nearby_fp_HmacSha256Update(const uint8_t* data, - size_t data_length); -// Finishes hash calculation. The parameters must match those passed to -// `nearby_fp_HmacSha256Start`. -// -// context - Context initalized with `nearby_fp_HmacSha256Start`. -// key - Input key to calculate hash. -// key_length - Length of key. -nearby_platform_status nearby_fp_HmacSha256Finish( - nearby_fp_HmacSha256Context* context, const uint8_t* key, - size_t key_length); - -// Implements HKDF-Extract method with SHA256 hash per -// https://www.rfc-editor.org/rfc/rfc5869#section-2.2 -// -// out - output Pseudo Random Key material -// salt - optional salt -// salt_length - salt length in bytes. Set to 0 when `salt is NULL -// ikm - Input Key Material -// ikm_length - IKM length in bytes -nearby_platform_status nearby_fp_HkdfExtractSha256(uint8_t out[SHA256_KEY_SIZE], - const uint8_t* salt, - size_t salt_length, - const uint8_t* ikm, - size_t ikm_length); - -// Implements HKDF-Expand with SHA256 hash per -// https://www.rfc-editor.org/rfc/rfc5869#section-2.3 -// -// out - Output Key Material -// out_length - OKM length in bytes -// prk - Pseudo Random Key -// prk_length - PRK length in bytes -// info - optional context information -// info_length - info length in bytes. Set to 0 when `info` is NULL. -nearby_platform_status nearby_fp_HkdfExpandSha256( - uint8_t* out, size_t out_length, const uint8_t* prk, size_t prk_length, - const uint8_t* info, size_t info_length); - -const uint8_t* nearby_fp_FindLtv(const uint8_t* advertisement, int type); - -// Calculates HMAC SHA256 hash. -// -// out - Output buffer for hash. -// key - Input key to calculate hash. -// key_length - Length of key. -// data - Data to calculate hash. -// data_length - Data length. -nearby_platform_status nearby_fp_HmacSha256(uint8_t out[32], const uint8_t* key, - size_t key_length, - const uint8_t* data, - size_t data_length); - -// The first 8 bytes of the message are the nonce. The message is -// encrypted/decrypted in place. -// -// message - Message buffer in/out. -// message_length - Length of message. -// key - Key. -nearby_platform_status nearby_fp_AesCtr( - uint8_t* message, size_t message_length, - const uint8_t key[AES_MESSAGE_SIZE_BYTES]); - -// Encrypts |data| in place: data = data ^ AES(key, iv). The data must -// be shorter than AES_MESSAGE_SIZE_BYTES. -// Side effect: |iv| contents are destroyed. -nearby_platform_status nearby_fp_AesEncryptIv( - uint8_t* data, size_t length, uint8_t iv[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]); - -#if NEARBY_FP_ENABLE_ADDITIONAL_DATA -// Decodes data package read from Additional Data characteristics. The decoding -// happens in-place. Returns an error if HMAC-SHA checksum is invalid. -// -// data - Data to decode. -// length - Length of data. -// key - Key. -nearby_platform_status nearby_fp_DecodeAdditionalData( - uint8_t* data, size_t length, const uint8_t key[ACCOUNT_KEY_SIZE_BYTES]); - -// Encodes data package for writing to Additional Data characteristics. The -// encoding happens in-place. The first 16 bytes of the data buffer are used for -// checksum and nonce, so the actual message must begin at offset 16. -// -// data - Data to encode. -// length - Length of data. -// key - Key. -nearby_platform_status nearby_fp_EncodeAdditionalData( - uint8_t* data, size_t length, const uint8_t key[ACCOUNT_KEY_SIZE_BYTES]); - -#endif /* NEARBY_FP_ENABLE_ADDITIONAL_DATA */ - -// Computes sha256 sum. -// -// out - Output 256 bit sum. -// data - Data to compute sha256 sum over. -// length - Length of data. -nearby_platform_status nearby_fp_Sha256(uint8_t out[32], const void* data, - size_t length); - -uint8_t nearby_fp_GetSassConnectionState(); - -size_t nearby_fp_GenerateSassAdvertisement( - uint8_t* advertisement, size_t length, uint8_t connection_state, - uint8_t custom_data, const uint8_t* devices_bitmap, size_t bitmap_length); - -uint16_t nearby_fp_GetSassCapabilityFlags(); - -nearby_platform_status nearby_fp_VerifyMessageAuthenticationCode( - const uint8_t* message, size_t length, - const uint8_t key[ACCOUNT_KEY_SIZE_BYTES], - const uint8_t session_nonce[SESSION_NONCE_SIZE]); - -// Encrypts Random Resolvable Field in place. The payload must start -// at RRF_HEADER_SIZE offset in the |data| buffer. |salt_field| is a -// part of non-discoverable advertisement -nearby_platform_status nearby_fp_EncryptRandomResolvableField( - uint8_t* data, size_t length, const uint8_t key[AES_MESSAGE_SIZE_BYTES], - const uint8_t* salt_field); -#ifdef __cplusplus -} -#endif - -#endif // NEARBY_FP_LIBRARY_H diff --git a/embedded/common/source/nearby_message_stream.c b/embedded/common/source/nearby_message_stream.c deleted file mode 100644 index 62da1fc6..00000000 --- a/embedded/common/source/nearby_message_stream.c +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 "nearby_message_stream.h" - -#include "nearby_platform_bt.h" - -#define HEADER_SIZE 4 -#define ACK_MESSAGE_SIZE 6 -#define NACK_MESSAGE_SIZE 7 -#define ACKNOWLEDGEMENT_GROUP 0xFF -#define ACK_CODE 1 -#define NACK_CODE 2 - -#if NEARBY_FP_MESSAGE_STREAM -void nearby_message_stream_Init(const nearby_message_stream_State* state) { - nearby_message_stream_Metadata* metadata = - (nearby_message_stream_Metadata*)state->buffer; - memset(metadata, 0, sizeof(nearby_message_stream_Metadata)); - metadata->message.data = - state->buffer + sizeof(nearby_message_stream_Metadata); -} - -void nearby_message_stream_Read(const nearby_message_stream_State* state, - const uint8_t* data, size_t length) { - nearby_message_stream_Metadata* metadata = - (nearby_message_stream_Metadata*)state->buffer; - nearby_message_stream_Message* message = &metadata->message; - uint16_t available_space = - state->length - sizeof(nearby_message_stream_Metadata); - while (length > 0) { - switch (metadata->bytes_read) { - case 0: - message->message_group = *data; - break; - case 1: - message->message_code = *data; - break; - case 2: - message->length = ((uint16_t)*data) << 8; - break; - case 3: - message->length += *data; - break; - default: { - uint16_t offset = metadata->bytes_read - HEADER_SIZE; - if (offset < message->length && offset < available_space) { - message->data[offset] = *data; - } - } - } - data++; - length--; - metadata->bytes_read++; - if (metadata->bytes_read - HEADER_SIZE == message->length) { - if (message->length > available_space) { - // Message truncated - message->length = available_space; - } - state->on_message_received(state->peer_address, message); - message->length = 0; - metadata->bytes_read = 0; - } - } -} - -nearby_platform_status nearby_message_stream_Send( - uint64_t peer_address, const nearby_message_stream_Message* message) { - nearby_platform_status status; - uint8_t header[HEADER_SIZE]; - header[0] = message->message_group; - header[1] = message->message_code; - header[2] = message->length >> 8; - header[3] = message->length; - status = - nearby_platform_SendMessageStream(peer_address, header, sizeof(header)); - if (kNearbyStatusOK == status && message->length > 0) { - status = nearby_platform_SendMessageStream(peer_address, message->data, - message->length); - } - return status; -} - -nearby_platform_status nearby_message_stream_SendAck( - uint64_t peer_address, const nearby_message_stream_Message* message) { - uint8_t ack[ACK_MESSAGE_SIZE]; - ack[0] = ACKNOWLEDGEMENT_GROUP; - ack[1] = ACK_CODE; - ack[2] = 0; - ack[3] = ACK_MESSAGE_SIZE - HEADER_SIZE; - ack[4] = message->message_group; - ack[5] = message->message_code; - return nearby_platform_SendMessageStream(peer_address, ack, sizeof(ack)); -} - -nearby_platform_status nearby_message_stream_SendNack( - uint64_t peer_address, const nearby_message_stream_Message* message, - uint8_t fail_reason) { - uint8_t nack[NACK_MESSAGE_SIZE]; - nack[0] = ACKNOWLEDGEMENT_GROUP; - nack[1] = NACK_CODE; - nack[2] = 0; - nack[3] = NACK_MESSAGE_SIZE - HEADER_SIZE; - nack[4] = fail_reason; - nack[5] = message->message_group; - nack[6] = message->message_code; - return nearby_platform_SendMessageStream(peer_address, nack, sizeof(nack)); -} - -uint16_t nearby_message_stream_GetMaxPayloadSize( - const nearby_message_stream_State* state) { - return state->length - sizeof(nearby_message_stream_Metadata); -} - -#endif /* NEARBY_FP_MESSAGE_STREAM */ diff --git a/embedded/common/source/nearby_message_stream.h b/embedded/common/source/nearby_message_stream.h deleted file mode 100644 index fb595f6b..00000000 --- a/embedded/common/source/nearby_message_stream.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_MESSAGE_STREAM_H -#define NEARBY_MESSAGE_STREAM_H - -// clang-format off -#include "nearby_config.h" -// clang-format on - -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -// Message group and codes for ACK and NACK messages -#define ACKNOWLEDGEMENT_GROUP 0xFF -#define ACK_CODE 1 -#define NACK_CODE 2 - -#define FAIL_REASON_INVALID_MAC 3 -#define FAIL_REASON_REDUNDANT_DEVICE_ACTION 4 - -// Message sent and received over the message stream -// See: https://developers.google.com/nearby/fast-pair/spec#MessageStream -typedef struct { - uint8_t message_group; - uint8_t message_code; - // |data| length in native encoding - uint16_t length; - // message payload in big endian encoding - uint8_t* data; -} nearby_message_stream_Message; - -// State and configuration of message stream parser -typedef struct { - // Callback triggered when a complete message is read from the input stream - void (*on_message_received)(uint64_t peer_address, - nearby_message_stream_Message* message); - // |peer_address| that is passed to |on_message_received| - uint64_t peer_address; - // Length of |buffer| - size_t length; - // The buffer used for storing an incoming message. The parser uses the buffer - // to store nearby_message_stream_Metadata, so not all of the space is - // available for message payload - uint8_t* buffer; -} nearby_message_stream_State; - -typedef struct { - nearby_message_stream_Message message; - uint16_t bytes_read; -} nearby_message_stream_Metadata; - -#if NEARBY_FP_MESSAGE_STREAM -// Initializes the parser -void nearby_message_stream_Init(const nearby_message_stream_State* state); - -// Reads and deserializes data from an input stream. It is OK to pass in -// incomplete packets. When the parses reads a complete message, it calls -// |on_message_received|. If the message payload is too big to fit the buffer - -// bigger than GetMaxPayloadSize(), then the payload is truncated. -void nearby_message_stream_Read(const nearby_message_stream_State* state, - const uint8_t* data, size_t length); - -// Serializes and sends |message| out using nearby_platform_SendMessageStream() -nearby_platform_status nearby_message_stream_Send( - uint64_t peer_address, const nearby_message_stream_Message* message); - -// Sends out an ACK message for a received |message|. Note that not all messages -// require an ACK -nearby_platform_status nearby_message_stream_SendAck( - uint64_t peer_address, const nearby_message_stream_Message* message); - -// Sends out a NACK message for a received |message| with |fail_reason| reason. -nearby_platform_status nearby_message_stream_SendNack( - uint64_t peer_address, const nearby_message_stream_Message* message, - uint8_t fail_reason); - -// Returns the maximum message payload size -uint16_t nearby_message_stream_GetMaxPayloadSize( - const nearby_message_stream_State* state); - -#endif /* NEARBY_FP_MESSAGE_STREAM */ -#ifdef __cplusplus -} -#endif - -#endif // NEARBY_MESSAGE_STREAM_H diff --git a/embedded/common/source/nearby_trace.h b/embedded/common/source/nearby_trace.h deleted file mode 100644 index 27f55da1..00000000 --- a/embedded/common/source/nearby_trace.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_TRACE_H -#define NEARBY_TRACE_H - -#include "nearby.h" -#include "nearby_platform_trace.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -// Must be kept in sync with TraceLevel in nearby_platform_trace.h -#define NEARBY_TRACE_LEVEL_VERBOSE (1) -#define NEARBY_TRACE_LEVEL_DEBUG (2) -#define NEARBY_TRACE_LEVEL_INFO (3) -#define NEARBY_TRACE_LEVEL_WARNING (4) -#define NEARBY_TRACE_LEVEL_ERROR (5) -#define NEARBY_TRACE_LEVEL_OFF (6) - -#if NEARBY_TRACE_LEVEL < NEARBY_TRACE_LEVEL_VERBOSE || \ - NEARBY_TRACE_LEVEL > NEARBY_TRACE_LEVEL_OFF -#error "Invalid definition of NEARBY_TRACE_LEVEL." -#endif - -#if NEARBY_TRACE_LEVEL > NEARBY_TRACE_LEVEL_VERBOSE -#define NEARBY_TRACE_VERBOSE(level, ...) -#else -#define NEARBY_TRACE_VERBOSE(level, ...) _NEARBY_TRACE(level, __VA_ARGS__) -#define NEARBY_ALL_ENUM_TO_STR_ENABLE 1 -#endif - -#if NEARBY_TRACE_LEVEL > NEARBY_TRACE_LEVEL_DEBUG -#define NEARBY_TRACE_DEBUG(level, ...) -#else -#define NEARBY_TRACE_DEBUG(level, ...) _NEARBY_TRACE(level, __VA_ARGS__) -#endif - -#if NEARBY_TRACE_LEVEL > NEARBY_TRACE_LEVEL_INFO -#define NEARBY_TRACE_INFO(level, ...) -#else -#define NEARBY_TRACE_INFO(level, ...) _NEARBY_TRACE(level, __VA_ARGS__) -#endif - -#if NEARBY_TRACE_LEVEL > NEARBY_TRACE_LEVEL_WARNING -#define NEARBY_TRACE_WARNING(level, ...) -#else -#define NEARBY_TRACE_WARNING(level, ...) _NEARBY_TRACE(level, __VA_ARGS__) -#endif - -#if NEARBY_TRACE_LEVEL > NEARBY_TRACE_LEVEL_ERROR -#define NEARBY_TRACE_ERROR(level, ...) -#else -#define NEARBY_TRACE_ERROR(level, ...) _NEARBY_TRACE(level, __VA_ARGS__) -#endif - -#ifndef __NEARBY_SHORT_FILE__ -#define __NEARBY_SHORT_FILE__ __FILE__ -#endif - -#define _NEARBY_TRACE(level, ...) \ - nearby_platform_Trace(level, __NEARBY_SHORT_FILE__, __LINE__, \ - "@g " __VA_ARGS__); - -#define NEARBY_TRACE(level, ...) \ - NEARBY_TRACE_##level((nearby_platform_TraceLevel)NEARBY_TRACE_LEVEL_##level, \ - __VA_ARGS__) -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_TRACE_H */ diff --git a/embedded/common/source/nearby_utils.c b/embedded/common/source/nearby_utils.c deleted file mode 100644 index 5fa665c3..00000000 --- a/embedded/common/source/nearby_utils.c +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 "nearby_utils.h" - -uint8_t nearby_utils_GetByte(uint64_t source, int byteNumber) { - return source >> (8 * byteNumber); -} - -void nearby_utils_CopyBigEndian(uint8_t* dest, uint64_t source, int bytes) { - int i; - for (i = 0; i < bytes; i++) { - dest[bytes - i - 1] = nearby_utils_GetByte(source, i); - } -} - -void nearby_utils_CopyLittleEndian(uint8_t* dest, uint64_t source, int bytes) { - int i; - for (i = 0; i < bytes; i++) { - dest[i] = nearby_utils_GetByte(source, i); - } -} - -uint32_t nearby_utils_GetBigEndian24(uint8_t* buffer) { - return (256 * 256 * buffer[0]) + (256 * buffer[1]) + buffer[2]; -} - -uint32_t nearby_utils_GetBigEndian32(uint8_t* buffer) { - return (256 * 256 * 256 * buffer[0]) + (256 * 256 * buffer[1]) + - (256 * buffer[2]) + buffer[3]; -} - -uint64_t nearby_utils_GetBigEndian48(uint8_t* b) { - return (((uint64_t)b[0]) << 40) | (((uint64_t)b[1]) << 32) | - (((uint64_t)b[2]) << 24) | (((uint64_t)b[3]) << 16) | - (((uint64_t)b[4]) << 8) | (uint64_t)b[5]; -} - -static char NibbleToHex(uint8_t value) { - if (value < 10) return '0' + value; - value -= 10; - if (value < 6) return 'A' + value; - return '?'; -} - -const char* nearby_utils_ArrayToString(const uint8_t* data, size_t length) { - static char buffer[80]; - size_t buffer_size = sizeof(buffer); - size_t num_bytes; - if (2 * length < buffer_size - 1) { - num_bytes = 2 * length; - buffer[num_bytes] = 0; - } else { - // The buffer is too small to hold all of data. Let's truncate the data and - // append an ellipsis. - num_bytes = buffer_size - 4; - buffer[buffer_size - 1] = 0; - buffer[buffer_size - 2] = '.'; - buffer[buffer_size - 3] = '.'; - buffer[buffer_size - 4] = '.'; - num_bytes = buffer_size - 4; - } - const uint8_t* input = data; - char* output = buffer; - for (size_t i = 0; i < num_bytes; i += 2) { - uint8_t x = *input++; - *output++ = NibbleToHex(x >> 4); - *output++ = NibbleToHex(x & 0x0F); - } - return buffer; -} - -const char* nearby_utils_MacToString(uint64_t address) { - static char buffer[18]; - char* p = buffer + sizeof(buffer) - 1; - *p-- = 0; - while (p > buffer) { - *p-- = NibbleToHex(address & 0xF); - address >>= 4; - *p-- = NibbleToHex(address & 0xF); - address >>= 4; - if (p >= buffer) *p-- = ':'; - } - return buffer; -} diff --git a/embedded/common/source/nearby_utils.cc b/embedded/common/source/nearby_utils.cc deleted file mode 100644 index c643dbff..00000000 --- a/embedded/common/source/nearby_utils.cc +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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. - diff --git a/embedded/common/source/nearby_utils.h b/embedded/common/source/nearby_utils.h deleted file mode 100644 index 5e24fba8..00000000 --- a/embedded/common/source/nearby_utils.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_UTILS_H -#define NEARBY_UTILS_H - -#include "nearby_types.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -uint8_t nearby_utils_GetByte(uint64_t source, int byteNumber); - -void nearby_utils_CopyBigEndian(uint8_t* dest, uint64_t source, int bytes); -void nearby_utils_CopyLittleEndian(uint8_t* dest, uint64_t source, int bytes); - -uint32_t nearby_utils_GetBigEndian24(uint8_t* buffer); -uint32_t nearby_utils_GetBigEndian32(uint8_t* buffer); -uint64_t nearby_utils_GetBigEndian48(uint8_t* buffer); - -// Converts the data to a hex string for debugging. Returns a pointer to a -// static buffer. Don't call it twice in the same log message! -const char* nearby_utils_ArrayToString(const uint8_t* data, size_t data_length); - -// Converts BT MAC address to string for debugging. Returns a pointer to a -// static buffer. Don't call it twice in the same log message! -const char* nearby_utils_MacToString(uint64_t address); - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_UTILS_H */ diff --git a/embedded/common/target/gLinux/nearby_types.h b/embedded/common/target/gLinux/nearby_types.h deleted file mode 100644 index 8abec318..00000000 --- a/embedded/common/target/gLinux/nearby_types.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_TYPES_H -#define NEARBY_TYPES_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifdef __cplusplus -} -#endif - -#endif // NEARBY_TYPES_H diff --git a/embedded/common/target/nearby.h b/embedded/common/target/nearby.h deleted file mode 100644 index 79bbf15f..00000000 --- a/embedded/common/target/nearby.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_H -#define NEARBY_H - -#include "nearby_types.h" - -// clang-format off -#include "nearby_config.h" -// clang-format on - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#define AES_MESSAGE_SIZE_BYTES 16 -#define FP_SERVICE_UUID_SIZE 2 -#define FP_MODEL_ID_SIZE 3 -// Nearby stores BT addresses as uint64_t values -#define FP_BT_ADDRESS_SIZE sizeof(uint64_t) -#define ACCOUNT_KEY_SIZE_BYTES AES_MESSAGE_SIZE_BYTES -#define SESSION_NONCE_SIZE 8 - -typedef struct { - uint8_t account_key[ACCOUNT_KEY_SIZE_BYTES]; -#ifdef NEARBY_FP_ENABLE_SASS - uint64_t peer_address; -#endif /* NEARBY_FP_ENABLE_SASS */ -} nearby_platform_AccountKeyInfo; - -#define NEARBY_FP_ACCOUNT_KEY_INFO_SIZE sizeof(nearby_platform_AccountKeyInfo) - -typedef enum { - kNearbyStatusOK = 0, - kNearbyStatusError, - kNearbyStatusTimeout, - kNearbyStatusResourceExhausted, - kNearbyStatusUnimplemented, - kNearbyStatusUnsupported, - kNearbyStatusInvalidInput, - kNearbyStatusRedundantAction -} nearby_platform_status; - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_H */ diff --git a/embedded/common/target/nearby_platform_audio.h b/embedded/common/target/nearby_platform_audio.h deleted file mode 100644 index 5b26e7d0..00000000 --- a/embedded/common/target/nearby_platform_audio.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2021 Google LLC. -#ifndef NEARBY_PLATFORM_AUDIO_H -#define NEARBY_PLATFORM_AUDIO_H - -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#define NEARBY_PLATFORM_CONNECTION_STATE_NO_CONNECTION 0 -#define NEARBY_PLATFORM_CONNECTION_STATE_PAGING 1 -#define NEARBY_PLATFORM_CONNECTION_STATE_NO_DATA_TRANFER 2 -#define NEARBY_PLATFORM_CONNECTION_STATE_NON_AUDIO_DATA_TRANSFER 3 -#define NEARBY_PLATFORM_CONNECTION_STATE_A2DP 4 -#define NEARBY_PLATFORM_CONNECTION_STATE_A2DP_WITH_AVRCP 5 -#define NEARBY_PLATFORM_CONNECTION_STATE_HFP 6 -#define NEARBY_PLATFORM_CONNECTION_STATE_LE_MEDIA_WITHOUT_CONTROL 7 -#define NEARBY_PLATFORM_CONNECTION_STATE_LE_MEDIA_WITH_CONTROL 8 -#define NEARBY_PLATFORM_CONNECTION_STATE_LE_CALL 9 -#define NEARBY_PLATFORM_CONNECTION_STATE_LE_BIS 10 -#define NEARBY_PLATFORM_CONNECTION_STATE_DISABLED_CONNECTION_SWITCH 15 - -// Multipoint switching preference flag bits. Every bit represents "new profile -// request" vs "current profile request". 1 - preference for switching, 0 - -// preference for not switching -#define NEARBY_SASS_SWITCHING_PREFERENCE_A2DP_VS_A2DP_MASK (1 << 7) -#define NEARBY_SASS_SWITCHING_PREFERENCE_HFP_VS_HFP_MASK (1 << 6) -#define NEARBY_SASS_SWITCHING_PREFERENCE_A2DP_VS_HFP_MASK (1 << 5) -#define NEARBY_SASS_SWITCHING_PREFERENCE_HFP_VS_A2DP_MASK (1 << 4) - -// Flags for SwitchActiveAudioSource -// 1 switch to this device, 0 switch to second connected device -#define NEARBY_SASS_SWITCH_ACTIVE_AUDIO_SOURCE_THIS_DEVICE_MASK (1 << 7) -// Resume playing on switch to device after switching, 0 otherwise. Resuming -// playing means the Provider sends a PLAY notification to the Seeker through -// AVRCP profile. If the previous state (before switched away) was not PLAY, the -// Provider should ignore this flag. -#define NEARBY_SASS_SWITCH_ACTIVE_AUDIO_SOURCE_RESUME_MASK (1 << 6) -// 1 reject SCO on switched away device, 0 otherwise -#define NEARBY_SASS_SWITCH_ACTIVE_AUDIO_SOURCE_REJECT_SCO_MASK (1 << 5) -// 1 disconnect Bluetooth on switch away device, 0 otherwise. -#define NEARBY_SASS_SWITCH_ACTIVE_AUDIO_SOURCE_DISCONNECT_PREVIOUS_MASK (1 << 4) - -// Flags for SwitchBackAudioSource. Note that the flags below are not bitmasks. -#define NEARBY_SASS_SWITCH_BACK 0x01 -#define NEARBY_SASS_SWITCH_BACK_AND_RESUME 0x02 - -// Flags for NotifySassInitiatedConnection. Note that the flags below are not -// bitmasks. -#define NEARBY_SASS_CONNECTION_INITIATED_BY_SASS 0 -#define NEARBY_SASS_CONNECTION_NOT_INITIATED_BY_SASS 1 - -// Reasons for |on_multipoint_switch_event| -#define NEARBY_SASS_MULTIPOINT_SWITCH_REASON_UNKNOWN 0 -#define NEARBY_SASS_MULTIPOINT_SWITCH_REASON_A2DP 1 -#define NEARBY_SASS_MULTIPOINT_SWITCH_REASON_HFP 2 - -// Returns true if right earbud is active -bool nearby_platform_GetEarbudRightStatus(); - -// Returns true if left earbud is active -bool nearby_platform_GetEarbudLeftStatus(); - -typedef struct { - // The platform HAL should call this callback on audio state changes. That is, - // when any of the query methods would return a new value. - void (*on_state_change)(); - // This event should be called after a multipoint audio source switch. To make - // users aware of a multipoint-switch event taking place, SASS Seekers may - // show a notification to users. So the Provider should notify connected SASS - // Seekers about the switching event. - // |reason| is one of NEARBY_SASS_MULTIPOINT_SWITCH_REASON_* constants - // |peer_address| is the address the new audio source - // |name| is utf-8 encoded name of the new audio source or NULL if name is not - // known. - void (*on_multipoint_switch_event)(uint8_t reason, uint64_t peer_address, - const char* name); -} nearby_platform_AudioCallbacks; - -// Returns one of NEARBY_PLATFORM_CONNECTION_STATE_* values -// Call |nearby_platform_AudioCallbacks::on_state_change| when this state -// changes. -unsigned int nearby_platform_GetAudioConnectionState(); - -// Returns true if the device is on head (or in ear). -// Call |nearby_platform_AudioCallbacks::on_state_change| when on-head state -// changes. -bool nearby_platform_OnHead(); - -// Returns true if the device can accept another audio connection without -// dropping any of the existing connections. -// Call |nearby_platform_AudioCallbacks::on_state_change| when this state -// changes. -bool nearby_platform_CanAcceptConnection(); - -// When the device is in focus mode, connection switching is not allowed -// Call |nearby_platform_AudioCallbacks::on_state_change| when this state -// changes. -bool nearby_platform_InFocusMode(); - -// Returns true if the current connection is auto-recconnected, meaning it is -// not connected by the user. For multi-point connections, returns true if any -// of the existing connections is auto-reconnected. -// Call |nearby_platform_AudioCallbacks::on_state_change| when this state -// changes. -bool nearby_platform_AutoReconnected(); - -// Sets a bit in the |bitmap| for every connected peer. The bit stays cleared -// for bonded but not connected peers. The order change is acceptable if it is -// unavoidable, e.g. when users factory reset the headset or when the bonded -// device count reaches the upper limit. -// |length| is the |bitmap| length on input in bytes and used space on output. -// For example, if there are 5 bonded devices, then |length| should be set to 1. -// Call |nearby_platform_AudioCallbacks::on_state_change| when this state -// changes. -void nearby_platform_GetConnectionBitmap(uint8_t* bitmap, size_t* length); - -// Returns true is SASS state in On -bool nearby_platform_IsSassOn(); - -// Returns true if the device supports multipoint and it can be switched between -// on and off -bool nearby_platform_IsMultipointConfigurable(); - -// Returns true is multipoint in On -bool nearby_platform_IsMultipointOn(); - -// Returns true if the device supports OHD (even if it's turned off at the -// moment) -bool nearby_platform_IsOnHeadDetectionSupported(); - -// Returns true if OHD is supported and enabled -bool nearby_platform_IsOnHeadDetectionEnabled(); - -// Enables or disables multipoint -// When |enable| is false, the device should keep the connection with -// |peer_address| and disconnect other connections (if any) -nearby_platform_status nearby_platform_SetMultipoint(uint64_t peer_address, - bool enable); - -// Sets multipoint switching preference flags -nearby_platform_status nearby_platform_SetSwitchingPreference(uint8_t flags); - -// Gets switching preference flags -uint8_t nearby_platform_GetSwitchingPreference(); - -// Switches active audio source (to a connected device). If the flags indicate a -// switch to |peer_address| device but |peer_address| is already the active -// device, then return kNearbyStatusRedundantAction. -// If the flags indicate a switch to another device, then -// |preferred_audio_source| is the address of the next, preferred audio source. -// |preferred_audio_source| is 0 if Nearby SDK cannot figure out what the next -// audio source should be. It may happen if they are no other connected Seekers. -nearby_platform_status nearby_platform_SwitchActiveAudioSource( - uint64_t peer_address, uint8_t flags, uint64_t preferred_audio_source); - -// Switches back to a disconnected audio source. -// |peer_address| is the address of the seeker who sent this command, *not* the -// address of the audio source that the device should switch to. The device -// should connect to the previous, currently disconnected, audio source and -// disconnect from |peer_address|. Ideally, the device should disconnect from -// |peer_address| after returning from this function. This would give Nearby SDK -// a chance to send an ACK message to the seeker. -nearby_platform_status nearby_platform_SwitchBackAudioSource( - uint64_t peer_address, uint8_t flags); - -// Notifies the platform if the connection was initiated by SASS. SASS Providers -// may need to know if the connection switching is triggered by SASS to have -// different reactions, e.g. disable earcons for SASS events. The Seeker sends a -// message to notify the Provider that this connection was a SASS initiated -// connection. -nearby_platform_status nearby_platform_NotifySassInitiatedConnection( - uint64_t peer_address, uint8_t flags); - -// Sets drop connection target -// On multipoint headphones, if the preferred connection to be dropped is not -// the least recently used one, SASS Seekers can tell the Provider which device -// to be dropped by using the message below. -nearby_platform_status nearby_platform_SetDropConnectionTarget( - uint64_t peer_address, uint8_t flags); - -// Returns the BT address of the active audio source -// Call |nearby_platform_AudioCallbacks::on_state_change| when active audio -// source changes. -uint64_t nearby_platform_GetActiveAudioSource(); - -// Initializes Audio module -nearby_platform_status nearby_platform_AudioInit( - const nearby_platform_AudioCallbacks* audio_interface); - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_PLATFORM_AUDIO_H */ diff --git a/embedded/common/target/nearby_platform_battery.h b/embedded/common/target/nearby_platform_battery.h deleted file mode 100644 index f12f4d70..00000000 --- a/embedded/common/target/nearby_platform_battery.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_PLATFORM_BATTERY_H -#define NEARBY_PLATFORM_BATTERY_H - -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef struct { - // Set to true if the device is charging. - bool is_charging; - // Battery level of the right bud. 0 - 100 range. - uint8_t right_bud_battery_level; - // Battery level of the left bud. 0 - 100 range. - uint8_t left_bud_battery_level; - // Battery level of the charging case . 0 - 100 range. - uint8_t charging_case_battery_level; - // Battery remaining time in minutes, 0-65335 range. - uint16_t remaining_time_minutes; -} nearby_platform_BatteryInfo; - -typedef struct { - void (*on_battery_changed)(void); -} nearby_platform_BatteryInterface; - -// Gets battery and charging info -// -// battery_info - Battery status structure. -nearby_platform_status nearby_platform_GetBatteryInfo( - nearby_platform_BatteryInfo* battery_info); - -// Initializes battery module -// -// battery_interface - Battery status callback events. -nearby_platform_status nearby_platform_BatteryInit( - nearby_platform_BatteryInterface* battery_interface); -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_PLATFORM_BATTERY_H */ diff --git a/embedded/common/target/nearby_platform_ble.h b/embedded/common/target/nearby_platform_ble.h deleted file mode 100644 index db5e54e3..00000000 --- a/embedded/common/target/nearby_platform_ble.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_PLATFORM_BLE_H -#define NEARBY_PLATFORM_BLE_H - -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef enum { - kModelId = 0, // FE2C1233-8366-4814-8EB0-01DE32100BEA (read) - kKeyBasedPairing, // FE2C1234-8366-4814-8EB0-01DE32100BEA (write, notify) - kPasskey, // FE2C1235-8366-4814-8EB0-01DE32100BEA (write, notify) - kAccountKey, // FE2C1236-8366-4814-8EB0-01DE32100BEA (write) - kFirmwareRevision, // 0x2A26 - kAdditionalData, // FE2C1237-8366-4814-8EB0-01DE32100BEA - // Message Stream PSM characteristic is required to establish an L2CAP - // communication channel between Seeker and Provider. Platforms that don't - // support L2CAP channel may choose not to implement this characteristic. - // By default, the Seeker connect to the Provider using RFCOMM. - kMessageStreamPsm, // FE2C1239-8366-4814-8EB0-01DE32100BEA (read, encrypted) -} nearby_fp_Characteristic; - -typedef enum { - kDisabled, - kNoLargerThan100ms, - kNoLargerThan250ms -} nearby_fp_AvertisementInterval; - -typedef struct { - nearby_platform_status (*on_gatt_write)( - uint64_t peer_address, nearby_fp_Characteristic characteristic, - const uint8_t* request, size_t length); - nearby_platform_status (*on_gatt_read)( - uint64_t peer_address, nearby_fp_Characteristic characteristic, - uint8_t* output, size_t* length); - -} nearby_platform_BleInterface; - -// Gets BLE address. -uint64_t nearby_platform_GetBleAddress(); - -// Sets BLE address. Returns address after change, which may be different than -// requested address. -// -// address - BLE address to set. -uint64_t nearby_platform_SetBleAddress(uint64_t address); - -#ifdef NEARBY_FP_HAVE_BLE_ADDRESS_ROTATION -// Rotates BLE address to a random resolvable private address (RPA). Returns -// address after change. -uint64_t nearby_platform_RotateBleAddress(); -#endif /* NEARBY_FP_HAVE_BLE_ADDRESS_ROTATION */ - -// Gets the PSM - Protocol and Service Mulitplexor - assigned to Fast Pair's -// Message Stream. -// To support Message Stream for BLE devices, Fast Pair will build and maintain -// a BLE L2CAP channel for sending and receiving messages. The PSM can be -// dynamic or fixed. -// Returns a 16 bit PSM number or a negative value on error. When a valid PSM -// number is returned, the device must be ready to accept L2CAP connections. -int32_t nearby_platform_GetMessageStreamPsm(); - -// Sends a notification to the connected GATT client. -// -// peer_address - Address of peer. -// characteristic - Characteristic UUID -// message - Message buffer to transmit. -// length - Length of message in buffer. -nearby_platform_status nearby_platform_GattNotify( - uint64_t peer_address, nearby_fp_Characteristic characteristic, - const uint8_t* message, size_t length); - -// Sets the Fast Pair advertisement payload and starts advertising at a given -// interval. -// -// payload - Advertising data. -// length - Length of data. -// interval - Advertising interval code. -nearby_platform_status nearby_platform_SetAdvertisement( - const uint8_t* payload, size_t length, - nearby_fp_AvertisementInterval interval); - -// Initializes BLE -// -// ble_interface - GATT read and write callbacks structure. -nearby_platform_status nearby_platform_BleInit( - const nearby_platform_BleInterface* ble_interface); - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_PLATFORM_BLE_H */ diff --git a/embedded/common/target/nearby_platform_bt.h b/embedded/common/target/nearby_platform_bt.h deleted file mode 100644 index 5b143d64..00000000 --- a/embedded/common/target/nearby_platform_bt.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_PLATFORM_BT_H -#define NEARBY_PLATFORM_BT_H - -// clang-format off -#include "nearby_config.h" -// clang-format on - -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef struct { - void (*on_pairing_request)(uint64_t peer_address); - void (*on_paired)(uint64_t peer_address); - void (*on_pairing_failed)(uint64_t peer_address); -#if NEARBY_FP_MESSAGE_STREAM - // Message Stream messages are sent over RFCOMM on BT devices or L2CAP on BLE - // devices. - void (*on_message_stream_connected)(uint64_t peer_address); - void (*on_message_stream_disconnected)(uint64_t peer_address); - void (*on_message_stream_received)(uint64_t peer_address, - const uint8_t* message, size_t length); -#endif /* NEARBY_FP_MESSAGE_STREAM */ -} nearby_platform_BtInterface; - -// Returns Fast Pair Model Id. -uint32_t nearby_platform_GetModelId(); - -// Returns tx power level. -int8_t nearby_platform_GetTxLevel(); - -// Returns public BR/EDR address. -// On a BLE-only device, return the public identity address. -uint64_t nearby_platform_GetPublicAddress(); - -// Returns the secondary identity address. -// Some devices, such as ear-buds, can advertise two identity addresses. In this -// case, the Seeker pairs with each address separately but treats them as a -// single logical device set. -// Return 0 if this device does not have a secondary identity address. -uint64_t nearby_platform_GetSecondaryPublicAddress(); - -// Returns passkey used during pairing -uint32_t nearby_platfrom_GetPairingPassKey(); - -// Provides the passkey received from the remote party. -// The system should compare local and remote party and accept/decline pairing -// request accordingly. -// -// passkey - Passkey -void nearby_platform_SetRemotePasskey(uint32_t passkey); - -// Sends a pairing request to the Seeker -// -// remote_party_br_edr_address - BT address of peer. -nearby_platform_status nearby_platform_SendPairingRequest( - uint64_t remote_party_br_edr_address); - -// Switches the device capabilities field back to default so that new -// pairings continue as expected. -nearby_platform_status nearby_platform_SetDefaultCapabilities(); - -// Switches the device capabilities field to Fast Pair required configuration: -// DisplayYes/No so that `confirm passkey` pairing method will be used. -nearby_platform_status nearby_platform_SetFastPairCapabilities(); - -// Sets null-terminated device name string in UTF-8 encoding -// -// name - Zero terminated string name of device. -nearby_platform_status nearby_platform_SetDeviceName(const char* name); - -// Gets null-terminated device name string in UTF-8 encoding -// pass buffer size in char, and get string length in char. -// -// name - Buffer to return name string. -// length - On input, the size of the name buffer. -// On output, returns size of name in buffer. -nearby_platform_status nearby_platform_GetDeviceName(char* name, - size_t* length); - -// Returns true if the device is in pairing mode (either fast-pair or manual). -bool nearby_platform_IsInPairingMode(); - -#if NEARBY_FP_MESSAGE_STREAM -// Sends message stream through RFCOMM or L2CAP channel initiated by Seeker. -// BT devices should use RFCOMM channel. BLE-only devices should use L2CAP. -// -// peer_address - Peer address. -// message - Contents of message. -// length - Length of message -nearby_platform_status nearby_platform_SendMessageStream(uint64_t peer_address, - const uint8_t* message, - size_t length); -#endif /* NEARBY_FP_MESSAGE_STREAM */ -// Initializes BT module -// -// bt_interface - BT callbacks event structure. -nearby_platform_status nearby_platform_BtInit( - const nearby_platform_BtInterface* bt_interface); - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_PLATFORM_BT_H */ diff --git a/embedded/common/target/nearby_platform_os.h b/embedded/common/target/nearby_platform_os.h deleted file mode 100644 index 0682addc..00000000 --- a/embedded/common/target/nearby_platform_os.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_PLATFORM_OS_H -#define NEARBY_PLATFORM_OS_H - -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef enum { - kRingStateStarted = 0, - kRingStateFailedToStartOrStop, - kRingStateStoppedReasonTimeout, - kRingStateStoppedReasonUserAction, - kRingStateStoppedReasonNearbyRequest -} nearby_platform_RingState; - -typedef struct { - nearby_platform_RingState ring_state; - // The number of components capable of ringing - // 0 - the device is incapable of ringing - // 1 - only a single component is capable of ringing - // 2 - left and right bud can ring - // 3 - left and right bud, and the case can ring - uint8_t num_components; - // A bitmap indicating what (sub)components are ringing. See - // `nearby_platform_Ring` for details - uint8_t components; - // Remaining ringing timeout in deciseconds - uint16_t timeout; -} nearby_platform_RingingInfo; - -// Gets current time in ms. -unsigned int nearby_platform_GetCurrentTimeMs(); - -// Starts a timer. Returns an opaque timer handle or null on error. -// -// callback - Function to call when timer matures. -// delay_ms - Number of milliseconds to run the timer. -void* nearby_platform_StartTimer(void (*callback)(), unsigned int delay_ms); - -// Cancels a timer -// -// timer - Timer handle returned by StartTimer. -nearby_platform_status nearby_platform_CancelTimer(void* timer); - -// Initializes OS module -nearby_platform_status nearby_platform_OsInit(); - -// Starts ringing -// -// `command` - the requested ringing state as a bitmap: -// Bit 1 (0x01): ring right -// Bit 2 (0x02): ring left -// Bit 3 (0x04): ring case -// Alternatively, `command` hold a special value of 0xFF to ring all -// components that can ring. -// `timeout` - the timeout in deciseconds. The timeout overrides the one already -// in effect if any component of the device is already ringing. -nearby_platform_status nearby_platform_Ring(uint8_t command, uint16_t timeout); - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_PLATFORM_OS_H */ diff --git a/embedded/common/target/nearby_platform_persistence.h b/embedded/common/target/nearby_platform_persistence.h deleted file mode 100644 index d18b8ed5..00000000 --- a/embedded/common/target/nearby_platform_persistence.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_PLATFORM_PERSISTENCE_H -#define NEARBY_PLATFORM_PERSISTENCE_H - -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef enum { - kStoredKeyAccountKeyList, - kStoredKeyPersonalizedName -} nearby_fp_StoredKey; - -// Loads stored key -// -// key - Type of key to fetch. -// output - Buffer to contain retrieved key. -// length - On input, contains the size of the output buffer. -// On output, contains the Length of key. -nearby_platform_status nearby_platform_LoadValue(nearby_fp_StoredKey key, - uint8_t* output, - size_t* length); - -// Saves stored key -// -// key - Type of key to store. -// output - Buffer containing key to store. -// length - Length of key. -nearby_platform_status nearby_platform_SaveValue(nearby_fp_StoredKey key, - const uint8_t* input, - size_t length); - -// Initializes persistence module -nearby_platform_status nearby_platform_PersistenceInit(); - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_PLATFORM_PERSISTENCE_H */ diff --git a/embedded/common/target/nearby_platform_se.h b/embedded/common/target/nearby_platform_se.h deleted file mode 100644 index d1e4f4e1..00000000 --- a/embedded/common/target/nearby_platform_se.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_PLATFORM_SE_H -#define NEARBY_PLATFORM_SE_H -// clang-format off -#include "nearby_config.h" -// clang-format on -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -// Generates a random number. -uint8_t nearby_platform_Rand(); - -// Computes the sha256 incrementally. Sha256Start() is called first, then -// Sha256Update() one or more times, and finally Sha256Finish(). -nearby_platform_status nearby_platform_Sha256Start(); - -// Intermediate sha256 compute. -// -// data - Block of data to compute into sha256. -// length - Length of data to process. -nearby_platform_status nearby_platform_Sha256Update(const void* data, - size_t length); - -// Finishes sha256 compute. -// -// out - Contains the final 256 bit sha. -nearby_platform_status nearby_platform_Sha256Finish(uint8_t out[32]); - -// Encrypts a data block with AES128 in ECB mode. -// -// input - Input data block to be encrypted. -// output - Resulting encrypted block. -// key - 128 bit key to use for encryption. -nearby_platform_status nearby_platform_Aes128Encrypt( - const uint8_t input[AES_MESSAGE_SIZE_BYTES], - uint8_t output[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]); - -// Decrypts a data block with AES128 in ECB mode. -// -// input - Input data block to be decrypted. -// output - Resulting decrypted block. -// key - 128 bit key to use for decryption. -nearby_platform_status nearby_platform_Aes128Decrypt( - const uint8_t input[AES_MESSAGE_SIZE_BYTES], - uint8_t output[AES_MESSAGE_SIZE_BYTES], - const uint8_t key[AES_MESSAGE_SIZE_BYTES]); - -// Generates a shared sec256p1 secret using remote party public key and this -// device's private key. -// -// remote_party_public_key - Remote key. -// secret - 256 bit shared secret. -nearby_platform_status nearby_platform_GenSec256r1Secret( - const uint8_t remote_party_public_key[64], uint8_t secret[32]); - -// Returns anti-spoofing 128 bit private key. -// Only used if the implementation also uses the -// nearby_platform_GenSec256r1Secret() routine defined in gen_secret.c. -// Return NULL if not implemented. -const uint8_t* nearby_platform_GetAntiSpoofingPrivateKey(); - -// Initializes secure element module -nearby_platform_status nearby_platform_SecureElementInit(); - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_PLATFORM_SE_H */ diff --git a/embedded/common/target/nearby_platform_trace.h b/embedded/common/target/nearby_platform_trace.h deleted file mode 100644 index d38233fa..00000000 --- a/embedded/common/target/nearby_platform_trace.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 NEARBY_PLATFORM_TRACE_H -#define NEARBY_PLATFORM_TRACE_H - -#include "nearby.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef enum { - kTraceLevelUnknown = 0, - kTraceLevelVerbose = 1, - kTraceLevelDebug = 2, - kTraceLevelInfo = 3, - kTraceLevelWarning = 4, - kTraceLevelError = 5, -} nearby_platform_TraceLevel; - -// Generates conditional trace line. This is usually wrapped in a macro to -// provide compiler parameters. -// -// level - Debug level, higher is less messages. -// filename - Name of file calling trace. -// lineno - Source line of trace call. -// fmt - printf() style format string (%). -// ... - A series of parameters indicated by the fmt string. -void nearby_platform_Trace(nearby_platform_TraceLevel level, - const char *filename, int lineno, const char *fmt, - ...); - -// Processes assert. Processes a failed assertion. -// -// filename - Name of file calling assert. -// lineno - Source line of assert call -// reason - String message indicating reason for assert. -void nearby_platfrom_CrashOnAssert(const char *filename, int lineno, - const char *reason); - -// Initializes trace module. -void nearby_platform_TraceInit(void); - -#ifdef __cplusplus -} -#endif - -#endif /* NEARBY_PLATFORM_TRACE_H */ diff --git a/embedded/release_notes.md b/embedded/release_notes.md deleted file mode 100644 index bd331dbc..00000000 --- a/embedded/release_notes.md +++ /dev/null @@ -1,35 +0,0 @@ - -### Nearby SDK for embedded systems release notes - -## v1.1.0-embedded-RC1 -Support GFPS 3.2 specification per [specification](https://developers.google.com/nearby/fast-pair/specifications/introduction). - -New features: -* Smart Audio Source Switching (SASS) -* Two byte salt for improved security - -Other changes: -* Added optional encryption modules based on mbedtls. -* Fixed build issues. -* More verbose and readable logs. - -Supported features include: -* Initial pairing with discoverable advertisement -* Subsequent pairing with non-discoverable advertisement -* Retroactive Active Key for provisioning after manual pairing -* Battery Notification -* Personalized Name -* RFCOMM message stream -* Unit-tests on a simulated gLinux platform implementation - -## v1.0.0-embedded -Initial release supporting GFPS 3.1 per [specification](https://developers.google.com/nearby/fast-pair/specifications/introduction). - -Supported features include: -* Initial pairing with discoverable advertisement -* Subsequent pairing with non-discoverable advertisement -* Retroactive Active Key for provisioning after manual pairing -* Battery Notification -* Personalized Name -* RFCOMM message stream -* Unit-tests on a simulated gLinux platform implementation diff --git a/embedded/target/gLinux/config.mk b/embedded/target/gLinux/config.mk deleted file mode 100644 index f5aa00c5..00000000 --- a/embedded/target/gLinux/config.mk +++ /dev/null @@ -1,47 +0,0 @@ -# Use MBEDTLS for test SSL implementation instead of OPENSSL -# Compiles in mbedtls implementation of a number of functions in se.h -NEARBY_PLATFORM_USE_MBEDTLS ?= 0 -# Use the hardware SE to generate the secp256r1 secret. Alternatively, generate -# the secret in software. -NEARBY_PLATFORM_HAS_SE ?= 1 - -CFLAGS_EXTRA ?= -CFLAGS += -g \ - -MD \ - -Werror \ - -Wno-deprecated-declarations \ - -DARCH_GLINUX \ - -fsanitize=address \ - -fno-omit-frame-pointer \ - -DARCH_GLINUX \ - -DNEARBY_ALL_MODULE_DEBUG \ - -DNEARBY_UNIT_TEST_ENABLED \ - $(CFLAGS_EXTRA) - -NEARBY_TRACE_LEVEL = VERBOSE - -ifeq ($(OPTIMIZED_BUILD),1) -CFLAGS += -O2 -else -CFLAGS += -O0 -endif - -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -CFLAGS += -DNEARBY_PLATFORM_USE_MBEDTLS -endif - -ifeq ($(NEARBY_PLATFORM_HAS_SE),1) -CFLAGS += -DNEARBY_PLATFORM_HAS_SE -endif - -TEST_INCLUDES = \ - -I$(GTEST_DIR)/include -I$(GTEST_DIR) \ - -I$(GMOCK_DIR)/include -I$(GMOCK_DIR) \ - $(CLIENT_INCLUDES) \ - -Iclient/tests/ \ - -Iclient/tests/$(ARCH)/ \ - -Iclient/tests/mocks/ - -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -TEST_INCLUDES += -I$(MBEDTLS_DIR)/include -endif \ No newline at end of file diff --git a/embedded/target/gLinux/rules.mk b/embedded/target/gLinux/rules.mk deleted file mode 100644 index 7724f20f..00000000 --- a/embedded/target/gLinux/rules.mk +++ /dev/null @@ -1,122 +0,0 @@ -ifneq ($(EXCLUDE_COMMON_TEST_SRCS),1) -TEST_SRCS += $(wildcard $(COMMON_DIR)/tests/*.cc) -endif - -TEST_SRCS += $(wildcard client/tests/*.cc) - -TEST_SRCS := $(filter-out $(TEST_SRCS_EXCLUDE), $(TEST_SRCS)) - -TEST_OBJS += $(patsubst %.cc,$(OUT_DIR)/%.o,$(TEST_SRCS)) -GLINUX_TARGET_SRCS := $(wildcard client/tests/glinux/*.cc) -MBEDTLS_TARGET_SRCS := $(wildcard common/source/mbedtls/*.c) -GTEST_SRCS = $(GTEST_DIR)/src/gtest-all.cc $(GMOCK_DIR)/src/gmock-all.cc -EMPTY_TARGET_SRCS := $(wildcard client/tests/empty_target/*.c) - -GTEST_OBJS := $(patsubst %.cc,$(OUT_DIR)/%.o,$(GTEST_SRCS)) - -GLINUX_TARGET_OBJS := $(patsubst %.cc,$(OUT_DIR)/%.o,$(GLINUX_TARGET_SRCS)) -MBEDTLS_TARGET_OBJS := $(patsubst %.c,$(OUT_DIR)/%.o,$(MBEDTLS_TARGET_SRCS)) -EMPTY_TARGET_OBJS := $(patsubst %.c,$(OUT_DIR)/%.o,$(EMPTY_TARGET_SRCS)) - -ALL_TEST_OBJS += $(GLINUX_TARGET_OBJS) - -ALL_TEST_OBJS += $(TEST_OBJS) -ALL_TEST_OBJS += $(GTEST_OBJS) -ALL_TEST_OBJS += $(EMPTY_TARGET_OBJS) -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -ALL_TEST_OBJS += $(MBEDTLS_TARGET_OBJS) -endif - -# The glinux target layer -$(GLINUX_TARGET_OBJS) : $(OUT_DIR)/%.o: %.cc - $(call compile_c,$(TEST_INCLUDES) -I. -std=c++14 -c $(CFLAGS)) - -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -# Mbed TLS interface files -$(MBEDTLS_TARGET_OBJS) : $(OUT_DIR)/%.o: %.c - $(call compile_c,$(TEST_INCLUDES) -I. -std=c99 -c $(CFLAGS)) -endif - -$(EMPTY_TARGET_OBJS) : $(OUT_DIR)/%.o: %.c - $(info "compiling empty target object $<") - $(call compile_c,-I. $(EMPTY_TARGET_INC) -std=c99 -c $(CFLAGS)) - -$(TEST_OBJS) : $(FIRMWARE_VERSION_FILENAME) -$(TEST_OBJS) : $(OUT_DIR)/%.o: %.cc - $(call compile_c,$(TEST_INCLUDES) -I. -std=c++14 $(CFLAGS)) - -$(GTEST_OBJS) : $(OUT_DIR)/%.o : %.cc - $(call compile_c,$(TEST_INCLUDES) -std=c++14 $(CFLAGS)) - -TESTS_TO_RUN = $(patsubst %.cc,$(OUT_DIR)/%_run,$(TEST_SRCS)) -.PHONY: $(TESTS_TO_RUN) - -# Static pattern rule to execute the test binary. -$(TESTS_TO_RUN) : %_run : % - mkdir -p $(OUT_DIR)/test_logs/$(notdir $<)_logs/ - ./$< --gtest_output=xml:$(OUT_DIR)/test_logs/$(notdir $<)_logs/sponge_log.xml - -TARGET_OBJS ?= $(GLINUX_TARGET_OBJS) -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -TARGET_OBJS += $(MBEDTLS_TARGET_OBJS) -endif - -TARGET_OS_SRCS := $(wildcard client/tests/gLinux/*.cc) -TARGET_MBEDTLS_SRCS += $(wildcard common/source/mbedtls/*.c) -TARGET_OS_OBJS ?= $(patsubst %.cc,$(OUT_DIR)/%.o,$(TARGET_OS_SRCS)) -TARGET_MBEDTLS_OBJS ?= $(patsubst %.c,$(OUT_DIR)/%.o,$(TARGET_MBEDTLS_SRCS)) -$(TARGET_OS_OBJS) : $(OUT_DIR)/%.o: %.cc - $(call compile_c,$(TEST_INCLUDES) -I. -std=c++14 $(CFLAGS)) -$(TARGET_MBED_OBJS) : $(OUT_DIR)/%.o: %.c - $(call compile_c,$(TEST_INCLUDES) -I. -std=c++14 $(CFLAGS)) - -ALL_TEST_OBJS += $(TEST_OBJS) -ALL_TEST_OBJS += $(TARGET_OS_OBJS) -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -ALL_TEST_OBJS += $(TARGET_MBEDTLS_OBJS) -endif - -ALL_OBJS += $(ALL_TEST_OBJS) -# Must include the .d files for test sources here since gLinux.rules is included -# by makefile after after it includes $(DEPFILES). --include $(ALL_TEST_OBJS:.o=.d) - -EMPTY_TARGET_TEST = $(OUT_DIR)/client/tests/empty_target_test -$(EMPTY_TARGET_TEST) : TARGET_OBJS = $(EMPTY_TARGET_OBJS) -$(EMPTY_TARGET_TEST) : $(EMPTY_TARGET_OBJS) -TEST_BINARIES = $(patsubst %.cc,$(OUT_DIR)/%,$(TEST_SRCS)) -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -$(TEST_BINARIES) : $(NAME) $(GTEST_OBJS) $(GLINUX_TARGET_OBJS) $(MBEDTLS_TARGET_OBJS) -else -$(TEST_BINARIES) : $(NAME) $(GTEST_OBJS) $(GLINUX_TARGET_OBJS) -endif -$(TEST_BINARIES) : $(TARGET_OS_OBJS) - -LIBS ?= -L $(OUT_DIR) -lnearby -lcrypto -lssl -lpthread -lstdc++ - -ifeq ($(NEARBY_PLATFORM_USE_MBEDTLS),1) -MBEDTLS_LIBS = $(MBEDTLS_DIR)/library/libmbedtls.a $(MBEDTLS_DIR)/library/libmbedcrypto.a -$(MBEDTLS_LIBS) &: - cd $(MBEDTLS_DIR) && $(MAKE) -$(TEST_BINARIES) : $(MBEDTLS_LIBS) -LIBS += -L $(MBEDTLS_DIR)/library -lmbedtls -lmbedcrypto -endif - -$(TEST_BINARIES) : % : %.o - mkdir -p $(dir $@) - $(CC) -o $@ $< \ - $(CFLAGS) \ - $(TEST_INCLUDES) \ - $(GTEST_OBJS) \ - $(TARGET_OBJS) \ - $(TARGET_OS_OBJS) \ - -L /usr/local/lib \ - -std=c++14 \ - $(LIBS) - -run_tests: $(TESTS_TO_RUN) - -tests: $(TEST_BINARIES) - -run_tests : tests -.PHONY : tests run_tests diff --git a/third_party/mbedtls b/third_party/mbedtls deleted file mode 160000 index ff7a3462..00000000 --- a/third_party/mbedtls +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ff7a3462017d1fafa823f6e081fc12802f96f29c diff --git a/third_party/micro-ecc b/third_party/micro-ecc deleted file mode 160000 index fe8ed90a..00000000 --- a/third_party/micro-ecc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fe8ed90abc356347378eb25e2586e90df7be015a