blob: dd07b9ede3d498f09379c85b7ace951e379233f7 [file] [log] [blame]
/*
* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef _SM_H_
#define _SM_H_
#include "newblue-macros.h"
#include "hci.h"
#include "sg.h"
#include "types.h"
NEWBLUE_BEGIN_DECLS
#define L2C_FIXED_CH_NUM_SM 6
#define SM_BLOCK_LEN 16
#define SM_SIG_LEN 12
/* PAIRING STATE AND STRUCTURE DEFINITION FOR HIGHER LAYER INTERFACE API */
/* STATE: Initial state of pairing where nothing happens yet
* TRANSIT FROM: SM_PAIR_STATE_PAIRED,SM_PAIR_STATE_CANCELED and SM_PAIR_STATE_FAILED
* NOTE: This is a termination state of smUnpair().
*/
#define SM_PAIR_STATE_NOT_PAIRED 0
/* STATE: Pairing begins
* TRANSIT FROM: SM_PAIR_STATE_NOT_PAIR, SM_PAIR_STATE_PAIRED
* NOTE: This is NOT a termination state of smPair(). Transited from SM_PAIR_STATE_PAIRED
* if security requirements are enhanced in the new pairing request.
*/
#define SM_PAIR_STATE_START 1
/* STATE: Pairing finishes successfully
* TRANSIT FROM: SM_PAIR_STATE_NOT_PAIRED or SM_PAIR_STATE_PAIRED
* NOTE: This is a termination state of smPair().
*/
#define SM_PAIR_STATE_PAIRED 2
/* STATE: Pairing canceled
* TRANSIT FROM: SM_PAIR_STATE_START
* NOTE: This is a termination state of smUnpair(). Reset to SM_PAIR_STATE_NOT_PAIRED w/o
* notification.
*/
#define SM_PAIR_STATE_CANCELED 3
/* STATE: Pairing failed
* TRANSIT FROM: SM_PAIR_STATE_START
* NOTE: This is a termination state of smPair(). Reset to SM_PAIR_STATE_NOT_PAIRED w/o
* notification.
*/
#define SM_PAIR_STATE_FAILED 4
/* ERROR: No error
* NOTE: Come with SM_PAIR_STATE_PAIRED, SM_PAIR_STATE_START, SM_PAIR_STATE_CANCELED, and
* SM_PAIR_STATE_NOT_PAIRED.
*/
#define SM_PAIR_ERR_NONE 0
/* ERROR: Error where pairing was done with sufficient security requirements
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to fall back to SM_PAIR_PAIRED.
*/
#define SM_PAIR_ERR_ALREADY_PAIRED 1
/* ERROR: Error where pairing is currently in progress. There is no guarantee on meeting
* the security requirements of the new pairing request when the pairing finishes.
* NOTE: Come with SM_PAIR_STATE_FAILED. Observers needs to fall back to either
* SM_PAIR_PAIRED or SM_PAIR_NOT_PAIRED depends on the previous state.
*/
#define SM_PAIR_ERR_IN_PROGRESS 2
/* ERROR: Error where the parameters of pairing request are not provided or invalid
* NOTE: Come with SM_PAIR_STATE_FAILED. Observers needs to fall back to either
* SM_PAIR_PAIRED or SM_PAIR_NOT_PAIRED depends on the previous state.
*/
#define SM_PAIR_ERR_INVALID_PAIR_REQ 3
/* ERROR: Error where the passkey mismatched during pairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_PASSKEY_FAILED 4
/* ERROR: Error where the out of band pairing is not available locally
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_OOB_NOT_AVAILABLE 5
/* ERROR: Error where the authentication requirements by an user cannot be met by either us
* or a peer device during pairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_AUTH_REQ_INFEASIBLE 6
/* ERROR: Error where the confirmation value mismatched during pairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_CONF_VALUE_MISMATCHED 7
/* ERROR: Error where pairing is not supported by either us or a peer device
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_PAIRING_NOT_SUPPORTED 8
/* ERROR: Error where the encryption key length requested by a peer device is either invalid
* or insufficient
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_ENCR_KEY_SIZE 9
/* ERROR: Error where multiple pairing attempts were made by either us or a peer device when
* a new pairing session was not yet allowed
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_REPEATED_ATTEMPT 10
/* ERROR: Error where a peer device failed to provide the parsable/valid parameters in a SM
* command during pairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_INVALID_PARAM 11
/* ERROR: Error where memory failed to be allocated for pairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_MEMORY 12
/* ERROR: Error where we failed to establish a L2CAP connection for SM protocol
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_L2C_CONN 13
/* ERROR: Error where the device is not presented as a peer device for pairing/unpairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observers needs to fall back to either
* SM_PAIR_PAIRED or SM_PAIR_NOT_PAIRED depends on the previous state.
*/
#define SM_PAIR_ERR_NO_SUCH_DEVICE 14
/* ERROR: Error where a peer device failed to provide an invalid/unexpected SM command
* during pairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_UNEXPECTED_SM_CMD 15
/* ERROR: Error where we failed to send the SM command during pairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_SEND_SM_CMD 16
/* ERROR: Error where we failed to encrypt a L2CAP connection with expected security
* requirement OR we failed/refused to respond to the unexpected encryption
* request/result
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_ENCR_CONN 17
/* ERROR: Error where a peer device failed to provide an invalid/unexpected L2CAP event
* during pairing
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_UNEXPECTED_L2C_EVT 18
/* ERROR: Error where either us or a peer device failed to continue the pairing procedure
* due to lack of response to any SM/L2CAP command/event, and the pairing stalled
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_STALLED 19
/* ERROR: Error where there is unknown action taken by a peer device during OR pairing failed
* with an unspecified reason
* NOTE: Come with SM_PAIR_STATE_FAILED. Observer needs to transit to SM_PAIR_NOT_PAIRED.
*/
#define SM_PAIR_ERR_UNKNOWN 20
typedef uint8_t SmPairState;
typedef uint8_t SmPairErr;
/* SM calls this to notify an observer about the pairing state change event.
* observers need to cast pairStateChange to struct smPairStateChange, and there is no ownership
* transition.
*/
typedef void (*smPairStateChangeCbk)(void *observerData, const void *pairStateChange,
uniq_t observerId);
struct smPairStateChange {
SmPairState pairState;
SmPairErr pairErr;
struct bt_addr peerAddr;
};
struct smPasskeyDisplay {
bool valid; /* this indicate whether a passkey display is valid or not. if true,
the passkey value should be displayed; if false, the passkey
session is done or canceled */
uint32_t passkey; /* when Passkey Entry pairing is selected, this is the passkey we
generate for display. an observer is responsible of display the
value with range 000,000 to 999,999 without eliminating zeros or
propagate this value to the host of display */
struct bt_addr peerAddr; /* the peer device to display to */
};
/* SM calls this to notify an observer about the passkey generated for Passkey Entry pairing for
* display purpose. there is no ownership transition of struct smPasskeyDisplay.
*/
typedef void (*smPasskeyDisplayCbk)(void *observerData,
const struct smPasskeyDisplay *passkeyDisplay, uniq_t observerId);
struct smPasskeyRequest {
bool valid; /* this indicate whether a passkey request is valid or not. if true,
the passkey request should be displayed; if false, the passkey
request is done or canceled */
struct bt_addr peerAddr; /* the peer device which displays the passkey */
};
/* SM calls this to notify an observer about the passkey request for input purpose. there is no
* ownership transition of struct smPasskeyRequest.
*/
typedef void (*smPasskeyRequestCbk)(void *observerData,
const struct smPasskeyRequest *passkeyRequest, uniq_t observerId);
struct smPairSecurityRequirements {
bool bond; /* indicate whether the bonding should be performed with a peer device */
bool mitm; /* indicate whether man-in-the-middle protection is required */
};
/* HELPER FUNCTIONS */
/* call this to perform CMAC calculation */
void smSignatureCalc(sg m, const uint8_t *key, uint8_t *sig) NEWBLUE_EXPORT;
/* ONE TIME SM INIT/DEINIT */
/* call this to perform on-time init of SM */
bool smInit(void) NEWBLUE_EXPORT;
/* call this to perform on-time deinit of SM */
void smDeinit(void) NEWBLUE_EXPORT;
/* HIGHER LAYER INTERFACE API */
/* call this to register as an observer of the pairing state changes with peer devices */
uniq_t smRegisterPairStateObserver(void *observerData, smPairStateChangeCbk cbk) NEWBLUE_EXPORT;
/* call this to unregister as an observer of the pairing state changes with peer devices */
void smUnregisterPairStateObserver(uniq_t observerId) NEWBLUE_EXPORT;
/* call this to register as the observer of the pairing passkey display. there can be only one
* observer/handler registered.
*/
uniq_t smRegisterPasskeyDisplayObserver(void *observerData, smPasskeyDisplayCbk cbk)
NEWBLUE_EXPORT;
/* call this to unregister as the observer of the pairing passkey display */
void smUnregisterPasskeyDisplayObserver(uniq_t observerId) NEWBLUE_EXPORT;
/* call this to register as the observer of the pairing passkey request. there can be only one
* observer who is responsible for providing the passkey by calling smProvidePasskey once the input
* of passkey is done.
*/
uniq_t smRegisterPasskeyRequestObserver(void *observerData, smPasskeyRequestCbk cbk)
NEWBLUE_EXPORT;
/* call this to unregister as the observer of the pairing passkey request */
void smUnregisterPasskeyRequestObserver(uniq_t observerId) NEWBLUE_EXPORT;
/* call this to pair with a remote LE device, the state of pairing will notify via
* smPairStateChangeCbk
*/
void smPair(const struct bt_addr *addr,
const struct smPairSecurityRequirements *secReqs) NEWBLUE_EXPORT;
/* call this to cancel/unpair with a remote LE device, the state of pairing will notify via
* smPairStateChangeCbk
*/
void smUnpair(const struct bt_addr *addr) NEWBLUE_EXPORT;
/* call this to generate a resolvable private address for advertising */
bool smGenResolvableAddr(struct bt_addr *addr) NEWBLUE_EXPORT;
/* call this to generate a non-resolvable private address for advertising */
bool smGenNonResolvableAddr(struct bt_addr *addr) NEWBLUE_EXPORT;
/* call this to respond to the passkey request from addr */
void smProvidePasskey(const struct bt_addr *addr, bool provided, uint32_t passkey) NEWBLUE_EXPORT;
/* ONLY FOR UNITTEST PURPOSE */
void smEncryptForTest(uint8_t* dst, const uint8_t *src, const uint8_t *key);
void smCalcConfValForTest(uint8_t* out, const uint8_t *k, const uint8_t *r, uint64_t pres,
uint64_t preq, bool iat, uint64_t ia, bool rat, uint64_t ra);
void smCalcKeyForTest(uint8_t *out, const uint8_t *k, const uint8_t *r1, const uint8_t *r2);
uint32_t smAddressHashForTest(uint32_t r, const uint8_t *key);
NEWBLUE_END_DECLS
#endif /* _SM_H_ */