[meshcop] adding otJoinerDiscerner (#5137)

The `otJoinerDiscerner` enables new a mechanism for Thread
commissioning. The traditional Thread commissioning process uses
factory assigned EUI-64 of the device to derive the Joiner ID and
identify/filter a joiner (through steering data bloom filter). The
Joiner Discerner (which is an unsigned value along with a
user-specified bit length up to 64 bits) allows users to have more
control and do not rely on factory-assigned EUI-64.

On joiner side, when a a Joiner Discerner value is provided, the
Joiner code uses the discerner value to derive Joiner ID (appending a
random prefix to extend the value to 64 bits) and bloom filter.

On commissioner side, users can add different joiners providing either
an EUI-64 or an associated Joiner Discerner and the code accordingly
match the Joiner IDs and compute steering data bloom filter.
This commit is contained in:
Abtin Keshavarzian
2020-06-26 16:02:09 -07:00
committed by Jonathan Hui
parent 2ebdf874eb
commit 5210ca3eee
14 changed files with 914 additions and 178 deletions
+62 -8
View File
@@ -37,6 +37,7 @@
#include <openthread/dataset.h>
#include <openthread/ip6.h>
#include <openthread/joiner.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/toolchain.h>
@@ -114,17 +115,31 @@ typedef struct otCommissioningDataset
#define OT_PSKD_MAX_SIZE 32 ///< Size of a Joiner PSKd (bytes)
/**
* This enumeration defines a Joiner Info Typer.
*
*/
typedef enum otJoinerInfoType
{
OT_JOINER_INFO_TYPE_ANY = 0, ///< Accept any Joiner (no EUI64 or Discerner is specified).
OT_JOINER_INFO_TYPE_EUI64 = 1, ///< Joiner EUI-64 is specified (`mSharedId.mEui64` in `otJoinerInfo`).
OT_JOINER_INFO_TYPE_DISCERNER = 2, ///< Joiner Discerner is specified (`mSharedId.mDiscerner` in `otJoinerInfo`).
} otJoinerInfoType;
/**
* This structure represents a Joiner Info.
*
*/
typedef struct otJoinerInfo
{
otExtAddress mEui64; ///< Joiner eui64
char mPsk[OT_PSKD_MAX_SIZE + 1]; ///< Joiner pskd
uint32_t mExpirationTime; ///< Joiner expiration time in msec
bool mAny : 1; /// TRUE if eui64 isn't set, FALSE otherwise.
otJoinerInfoType mType; ///< Joiner type.
union
{
otExtAddress mEui64; ///< Joiner EUI64 (when `mType` is `OT_JOINER_INFO_TYPE_EUI64`)
otJoinerDiscerner mDiscerner; ///< Joiner Discerner (when `mType` is `OT_JOINER_INFO_TYPE_DISCERNER`)
} mSharedId; ///< Shared fields
char mPsk[OT_PSKD_MAX_SIZE + 1]; ///< Joiner PSKd
uint32_t mExpirationTime; ///< Joiner expiration time in msec
} otJoinerInfo;
/**
@@ -141,12 +156,14 @@ typedef void (*otCommissionerStateCallback)(otCommissionerState aState, void *aC
/**
* This function pointer is called whenever the joiner state changes.
*
* @param[in] aEvent The joiner event type.
* @param[in] aJoinerId A pointer to the Joiner ID.
* @param[in] aContext A pointer to application-specific context.
* @param[in] aEvent The joiner event type.
* @param[in] aJoinerInfo A pointer to the Joiner Info.
* @param[in] aJoinerId A pointer to the Joiner ID (if not known, it will be NULL).
* @param[in] aContext A pointer to application-specific context.
*
*/
typedef void (*otCommissionerJoinerCallback)(otCommissionerJoinerEvent aEvent,
const otJoinerInfo * aJoinerInfo,
const otExtAddress * aJoinerId,
void * aContext);
@@ -200,6 +217,27 @@ otError otCommissionerAddJoiner(otInstance * aInstance,
const char * aPskd,
uint32_t aTimeout);
/**
* This function adds a Joiner entry with a given Joiner Discerner value.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aDiscerner A pointer to the Joiner Discerner.
* @param[in] aPskd A pointer to the PSKd.
* @param[in] aTimeout A time after which a Joiner is automatically removed, in seconds.
*
* @retval OT_ERROR_NONE Successfully added the Joiner.
* @retval OT_ERROR_NO_BUFS No buffers available to add the Joiner.
* @retval OT_ERROR_INVALID_ARGS @p aDiscerner or @p aPskd is invalid.
* @retval OT_ERROR_INVALID_STATE The commissioner is not active.
*
* @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
*
*/
otError otCommissionerAddJoinerWithDiscerner(otInstance * aInstance,
const otJoinerDiscerner *aDiscerner,
const char * aPskd,
uint32_t aTimeout);
/**
* This method get joiner info at aIterator position.
*
@@ -229,6 +267,22 @@ otError otCommissionerGetNextJoinerInfo(otInstance *aInstance, uint16_t *aIterat
*/
otError otCommissionerRemoveJoiner(otInstance *aInstance, const otExtAddress *aEui64);
/**
* This function removes a Joiner entry.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aEui64 A pointer to the Joiner Discerner.
*
* @retval OT_ERROR_NONE Successfully removed the Joiner.
* @retval OT_ERROR_NOT_FOUND The Joiner specified by @p aEui64 was not found.
* @retval OT_ERROR_INVALID_ARGS @p aDiscerner is invalid.
* @retval OT_ERROR_INVALID_STATE The commissioner is not active.
*
* @note Only use this after successfully starting the Commissioner role with otCommissionerStart().
*
*/
otError otCommissionerRemoveJoinerWithDiscerner(otInstance *aInstance, const otJoinerDiscerner *aDiscerner);
/**
* This function gets the Provisioning URL.
*
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (7)
#define OPENTHREAD_API_VERSION (8)
/**
* @addtogroup api-instance
+49 -5
View File
@@ -69,6 +69,18 @@ typedef enum otJoinerState
OT_JOINER_STATE_JOINED = 5,
} otJoinerState;
#define OT_JOINER_MAX_DISCERNER_LENGTH 64 ///< Maximum length of a Joiner Discerner in bits.
/**
* This structure represents a Joiner Discerner.
*
*/
typedef struct otJoinerDiscerner
{
uint64_t mValue; ///< Discerner value (the lowest `mLength` bits specify the discerner).
uint8_t mLength; ///< Length (number of bits) - must be non-zero and at most `OT_JOINER_MAX_DISCERNER_LENGTH`.
} otJoinerDiscerner;
/**
* This function pointer is called to notify the completion of a join operation.
*
@@ -132,16 +144,48 @@ void otJoinerStop(otInstance *aInstance);
otJoinerState otJoinerGetState(otInstance *aInstance);
/**
* Get the Joiner ID.
* This method gets the Joiner ID.
*
* Joiner ID is the first 64 bits of the result of computing SHA-256 over factory-assigned
* IEEE EUI-64, which is used as IEEE 802.15.4 Extended Address during commissioning process.
* If a Joiner Discerner is not set, Joiner ID is the first 64 bits of the result of computing SHA-256 over
* factory-assigned IEEE EUI-64. Otherwise the Joiner ID is calculated from the Joiner Discerner value.
*
* The Joiner ID is also used as the device's IEEE 802.15.4 Extended Address during commissioning process.
*
* @param[in] aInstance A pointer to the OpenThread instance.
* @param[out] aJoinerId A pointer to where the Joiner ID is placed.
*
* @returns A pointer to the Joiner ID.
*
*/
void otJoinerGetId(otInstance *aInstance, otExtAddress *aJoinerId);
const otExtAddress *otJoinerGetId(otInstance *aInstance);
/**
* This method sets the Joiner Discerner.
*
* The Joiner Discerner is used to calculate the Joiner ID used during commissioning/joining process.
*
* By default (when a discerner is not provided or set to NULL), Joiner ID is derived as first 64 bits of the result
* of computing SHA-256 over factory-assigned IEEE EUI-64. Note that this is the main behavior expected by Thread
* specification.
*
* @param[in] aInstance A pointer to the OpenThread instance.
* @param[in] aDiscerner A pointer to a Joiner Discerner. If NULL clears any previously set discerner.
*
* @retval OT_ERROR_NONE The Joiner Discerner updated successfully.
* @retval OT_ERROR_INVALID_ARGS @p aDisciminrator is not valid (specified length is not within valid range).
* @retval OT_ERROR_INVALID_STATE There is an ongoing Joining process so Joiner Discerner could not be changed.
*
*/
otError otJoinerSetDiscerner(otInstance *aInstance, otJoinerDiscerner *aDiscerner);
/**
* This method gets the Joiner Discerner.
*
* @param[in] aInstance A pointer to the OpenThread instance.
*
* @returns A pointer to Joiner Discerner or NULL if none is set.
*
*/
const otJoinerDiscerner *otJoinerGetDiscerner(otInstance *aInstance);
/**
* @}