Describes SSP.
Secure Simple Pairing, introduced into Bluetooth v2.1, simplifies the user experience when pairing Bluetooth devices.
This document describes the Symbian platform implementation of SSP. It describes the tasks that must be performed by UI creators to implement SSP and it describes how application developers can use Symbian APIs to pair with Bluetooth enabled devices using SSP.
Scope
This document is intended for Symbian partners and developers implementing SSP on Symbian platform. It assumes that you are familiar with Bluetooth and with developing on Symbian platform.
Purpose of SSP
SSP was introduced to simplify the user experience when pairing Bluetooth devices. Specifically:
The pairing model
Pre-SSP pairing is achieved by the user(s) entering a personal identification number (PIN) on one or both devices. Devices with no keypads, such as headsets, have their PINs (typically "0000" or "1234") hard-wired. This is now referred to as Legacy Paring.
Under SSP, devices specify their authorisation requirements. The user may have to:
press a button in response to a simple yes or no query
compare two automatically generated numbers and select 'yes' if they match or 'no' if they do not
enter a number on one or both devices
do nothing
Once the devices have paired the user may be asked to authorise bonding. Bonded devices can subsequently pair with no user interaction.
Key concepts
Verification that a remote device is what it claims to be. Authentication may be unnecessary for some pairings (see Just Works), may require user intervention (see Man in the Middle) or may be performed through another channel (see Out of Band).
In legacy pairing a remote device can be authorised after pairing such that it subsequently connects automatically without user intervention. Authorisation is on a per-service basis. See bonding.
Transmission of data between devices after SSP is always encrypted. Under legacy pairing data transmission is not always encrypted.
Authentication explicitly provided by the user before pairing can take place. Under SSP, devices and services have hard-wired authentication requirements as follows: MITM required, MITM not required (see Just Works) and MITM desired (subject to the user interface capabilities of the devices)
For some pairings there is little risk of a security breach so SSP provides a mechanism for devices to pair with no explicit user authentication.
In the context of a Symbian device, which always has both a display and a keypad, passkey authentication is used when pairing with a remote device which has a keypad but no display. The Symbian device displays a number which the user must enter using the keypad on the remote device
Out of Band authentication is performed using a non-Bluetooth communication channel. The data required to open an MITM protected Bluetooth connection with a remote device is transmitted by other means.
Two devices may bond after athentication such that they can reconnect without user intervention. Bonding is achieved on a Symbian device by storing a link key. Symbian devices attempt to bond by default. The user or the remote device may specify that the devices do not bond.
When a connection is authenticated a link key is created. The link key indicates the strength of authentication (legacy, authenticated or unauthenticated). The link key may be stored by the Symbian device and used to bond (the default behaviour) or discarded when the connection ends. The link key is not displayed to the user.
Components
Most of the changes are internal and transparent to system creators and developers. However, some new APIs added to the Bluetooth User Library allow application developers to use SSP features, and Licensees must implement some SSP specific notifiers.
The diagram below shows the interfaces and interface classes required to implement SSP.
Dedicated Bonding
Dedicated bonding is performed by the Bluetooth Pairing Server. Applications can use the RBluetoothDedicatedBondingInitiator API to request bonding with a specified Bluetooth device.
Out of Band Data
Out of Band pairing data can be passed to the Bluetooth Pairing Server. The server can use the supplied data to pair with the specified device. Applications can also use the RBluetoothOobData API to retrieve OOB data for the local device to be passed to remote devices.
Numeric Comparison Notifier
The Bluetooth sub-system requires a Numeric Comparison Notifier to be provided by the UI. The notifier must handle TBTNumericComparisonParams and return a boolean value which indicates the user's decision.
Passkey Entry Notifier
The Bluetooth sub-system requires a Passkey Entry Notifier to be provided by the UI. The notifier must handle TBTPasskeyDisplayParams and TBTPasskeyDisplayUpdateParams.
Data Types
SSP specific data is stored and manipulated using the following types (significant functions and fields shown only). These types are used in various device and service related APIs. They are defined in bt_sock.h and btdevice.h.
#include <bt_sock.h>
enum TBluetoothMitmProtection { EMitmNotRequired = 0x0, // No Man-in-the-Middle authentication is not required. EMitmDesired = 0x1, // Man-in-the-Middle authentication should be used where possible. EMitmRequired = 0x2 // Man-in-the-Middle authentication is required. };
class TBTAccessRequirements { public: ... IMPORT_C void SetAuthentication( TBluetoothMitmProtection aPreference ); IMPORT_C TBluetoothMitmProtection MitmProtection() const; ... private: enum TBTServiceSecuritySettings { EAuthenticate = 0x01, EAuthorise = 0x02, EEncrypt = 0x04, EDenied = 0x08, EMitm = 0x30, // 2 bit field for MITM }; enum TBTAccessRequirementsMitmProtection { EAccessRequirementsMitmUndefined = 0x00, EAccessRequirementsMitmNotRequired = 0x10, EAccessRequirementsMitmDesired = 0x20, EAccessRequirementsMitmRequired = 0x30 }; };
class TBTServiceSecurity { public: ... IMPORT_C void SetAuthentication( TBluetoothMitmProtection aPreference ); IMPORT_C TBool AuthenticationRequired() const; IMPORT_C TBluetoothMitmProtection MitmProtection() const; ... private: TBTAccessRequirements iSecurityRequirements; // Whether the service requires authentication, authorisation, encryption or min passkey len. }; typedef TPckgBuf<TBTServiceSecurity> TBTServiceSecurityPckg; // Package definition for securty settings
#include <btdevice.h>
class TBTDeviceSecurity { public: // Enumeration to provide select MITM protection required. enum TMitmRequired { EMitmUnspecified, // No specific MITM protection requirements EMitmRequired // Require the link is MITM protected }; public: ... IMPORT_C void SetNoAuthenticate(TBool aDecision); IMPORT_C void SetMitmRequirements(TMitmRequired aDecision); ... IMPORT_C TBool NoAuthenticate() const; IMPORT_C TMitmRequired MitmRequirements() const; ... public: // Enumeration to assist in parsing of security settings. enum TBTDeviceSecuritySettings { ENoAuthenticate = 0x01, // Don't authenticate the link @deprecated ENoAuthorise = 0x02, // Don't authorise the connection EEncrypt = 0x04, // Encrypt the link EBanned = 0x08, // Don't connect to the device EMitmProtectionRequired = 0x10, // Require the link is MITM protected }; };
Introdution
The Bluetooth sub-system has no user interface. It uses the Symbian notifier framework for user interaction when pairing. The UI system must provide a notifier, in plug-in form, for each user interaction required by SSP. The notifier must receive data in a specified format from the Bluetooth sub-system, display appropriate controls in a dialog on the screen, respond to the user's input and send data back to the Bluetooth sub-system in a specified format.
This document assumes that you already have Bluetooth notifiers in your system. It describes the key aspects of adding notifiers for SSP. The structures, types and constants described below are defined in BTExtNotifiers.h. You can add notifiers to an existing plug-in or create a new plug-in.
Notifiers are typically implemented as sleeping dialogs. A sleeping dialog has its resources allocated when its application (in this case the Uikon Server) is started. A sleeping dialog can therefore be displayed (roused) safely under low memory conditions.
Notes:
This document does not describe how to implement an ECOM plug-in or a sleeping dialog.
Customisation Kit Licensees can find an example notifier implementation here: sf/mw/classicui/commonuisupport/uikon/examples/notifier1/
Numeric Comparison Notifier
A numeric comparison notifier is required for SSP Man in the Middle (MITM) authentication when the remote device is capable of displaying a number to the the user and accepting a yes or no response from the user. The notifier must display an automatically generated number and invite the user to confirm (yes or no) that the number is the same as the number displayed on the remote device. The notifier must return the user's response.
The Bluetooth Security Manager uses the following code to ask the notifier framework to display the Numeric Comparison Notifier
// defined in header file(s) TBTDevAddr iDevAddr ; RNotifier iNotifier ; TUint32 iNumericValue ; TBool iInternallyInitiated ; TBTNumericComparisonParamsPckg iNumericComparisonParamsPckg ; TPckgBuf<TBool> iResultPckg ; // void CBTNumericComparator::DoRequest() { // Start the RNotifier plugin that deals with authorisation. ... TBTDeviceName deviceName = KNullDesC ; iNumericComparisonParamsPckg = TBTNumericComparisonParams( iDevAddr, deviceName, iNumericValue, TBTNumericComparisonParams::ERemoteCanConfirm, iInternallyInitiated); iNotifier.StartNotifierAndGetResponse( iStatus, KBTNumericComparisonNotifierUid, iNumericComparisonParamsPckg, iResultPckg); SetActive(); }
From the code above you can see that the Numeric Comparision Notifier is identified by the UIDKBTNumericComparisonNotifierUid and that it must handle data in TBTNumericComparisonParams (which is packaged into TBTNumericComparisonParamsPckg for inter-process transfer).
The code fragment below shows how to extract the numeric comparison data within a notifier.
NOTE: You will need to implement all of the virtual functions in MEikSrvNotifierBase2.
class CNumericComparisonNotifier : public CEikDialog, public MEikSrvNotifierBase2 { public: ... // from MEikSrvNotifierBase2 void StartL ( const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage ) ; ... void Complete( TBool aDecision, TInt aReason ) ; private: TInt iRepySlot ; TNotifierInfo iInfo ; RMessage2 iMessage ; TBTNumeriComparisonParamsPckg iNumericComparisonParamsPckg ; TBTDevAddr iAddr ; TBTDeviceName iName ; TUint32 iNumericalValue ; } ; //-------------------------------- ... void CNumericComparisionNotifier::StartL( const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage ) { iMessage = RMessage2( aMessage ) ; // keep a copy ofthe message so that it can be completed later. iReplySlot = aReplySlot ; // copy the reply slot too // Extract the comparison parameters from the buffer iNumericComparisonParamsPckg.Copy( aBuffer ) ; iAddr = iNumericComparisonParamsPckg().DeviceAddress() ; iName = iNumericComparisonParamsPckg().DeviceName() ; iNumericalValue = iNumericComparisonParamsPckg().NumericalValue() ; ... RouseSleepingDialog() ; }
Your dialog must display iNumericalValue and ask the user if the number displayed is the same as the number displayed on the other Bluetooth device. The user must be able to select 'Yes' or 'No'.
The StartL() function above must return quickly so it must not wait for the user's response. Your notifier must complete the message (iMessage) as shown below when the user enters a response.
void CNumericComparisionNotifier::Complete( TBool aDecision, TInt aReason ) { if ( aReason == KErrNone ) { TInt err = iMessage.Write( iReplySlot, TPckgC<TBool>( aDecision ) ) ; iMessage.Complete( err ) ; } else { iMessage.Complete( aReason ) ; } }
Passkey Notifier
A passkey notifier is required for SSP MITM authentication when the user must type a number on a remote device which has a keypad and no display. The notifier displays the number that the user must type. In the code below the notifier also displays a '*' character as the user types each digit into the remote device.
The Bluetooth Security Manager uses the following code to ask the Notifier Framework to display the passkey notifier.
// defined in header file(s) TBTDevAddr iDevAddr ; RNotifier iNotifier ; TUint32 iNumericValue ; // the passkey number TBool iInternallyInitiated ; TBTPasskeyDisplayParamsPckg iPasskeyDisplayParamsPckg ; TBTDeviceNameUpdateParamsPckg iDeviceNameUpdateParamsPckg; TBuf8<1> iResultPckg ; void CBTPasskeyEntry::DoRequest() { // Start the RNotifier plugin that deals with authorisation. ... TBTDeviceName deviceName ; deviceName = KNullDesC ; iPasskeyDisplayParamsPckg = TBTPasskeyDisplayParams( iDevAddr, deviceName, iNumericValue, iInternallyInitiated ) ; iNotifier.StartNotifierAndGetResponse( iStatus, KBTPasskeyDisplayNotifierUid, iPasskeyDisplayParamsPckg, iResultPckg ) ; SetActive() ; }
From the code above you can see that the Passkey Notifier is identified by the UIDKBTPasskeyNotifierUid and that it must handle data in TBTPasskeyDisplayParams (which is packaged into TBTPasskeyDisplayParamsPckg for inter-process transfer).
As the user enters passkey digits into the remote device the Security Manager also uses RNotifier::UpdateNotifierAndGetResponse() to send TBTPasskeyDisplayUpdateParams (packaged in TBTPasskeyDisplayUdateParamsPckg) to the notifier. Your notifier must use this information to reflect the key presses on the remote device.
The code fragment below shows how to extract the passkey data within a notifier.
NOTE: You will need to implement all of the virtual functions in MEikSrvNotifierBase2.
class CPasskeyNotifier : public CEikDialog, public MEikSrvNotifierBase2 { public: ... // from MEikSrvNotifierBase2 void StartL( const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage ) ; TPtrC8 UpdateL( const TDesC8& aBuffer ) ; // new information ... private: TInt iRepySlot ; TNotifierInfo iInfo ; RMessage2 iMessage ; TBTPasskeyDisplayParamsPckg iPasskeyDisplayParamsPckg ; TBTDevAddr iAddr ; TBTDeviceName iName ; TUint32 iNumericalValue ; // the passkey number } ; //-------------------------------- ... void CPasskeyNotifier::StartL( const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage ) { iMessage = RMessage2(aMessage); // keep a copy ofthe message so that it can be completed later. iReplySlot = aReplySlot ; // copy the reply slot too // Extract the comparison parameters from the buffer iPasskeyDisplayParamsPckg.Copy( aBuffer ) ; iAddr = iPasskeyDisplayParamsPckg().DeviceAddress() ; iName = iPasskeyDisplayParamsPckg().DeviceName() ; iNumericValue = iPasskeyDisplayParamsPckg().NumericalValue() ; ... RouseSleepingDialog() ; // display the passkey ... } void CPasskeyNotifier::UpdateL( const TDesC8& aBuffer ) { // extract the contents of the buffer TBTNotifierUpdateParamsPckg2 pckgRaw ; pckgRaw.Copy( aBuffer.Left( pckgRaw.MaxLength() ) ) ; // update the dialog to reflect the keys pressed on the remote device if ( pckgRaw().Type() == TBTNotifierUpdateParams2::EPasskeyDisplay ) { TBTPasskeyDisplayUpdateParamsPckg pckg ; pckg.Copy( aBuffer ) ; HCIPasskeyEntryNotificationType keypressNotification = pckg().KeypressNotification() ; switch (keypressNotification) { case EPasskeyEntryStarted : { break ; } case EPasskeyDigitEntered : { // display '*' break ; } case EPasskeyDigitDeleted : { // remove '*', reposition cursor break ; } case EPasskeyCleared : { // clear display, reposition cursor break ; } case EPasskeyEntryCompleted : { // hide the dialog ExitSleepingDialog() ; break; } default : break ; } else if( pckgRaw().Type() == TBTNotifierUpdateParams2::EDeviceName ) { // handle name update } return KNullDesC8() ; }
Introduction
Out of Band authentication is achieved using a communication method other than Bluetooth. Once OOB authentication has succeeded an encrypted Bluetooth channel is opened between the two devices.
The OOB API, RBluetoothOobData, allows an application handling OOB authentication to provide pairing information for a remote device.
RBluetoothOobData allows an application handling OOB authentication to retrieve pairing information for the local device.
Using the OOB API
The OOB data API is provided by the Pairing Server (part of the Security Manager).
#include <pairing.h> RBluetoothPairingServer pairingServer ; RBluetoothOobData OobData ; // Connect to the Pairing server TInt err = pairingServer.connect() ; // Paring session err = OobData.Open( iPairingServer ) ; // Use the API pass hash and randomizer values to and from the pairing server. ... // Tidy up OobData.Close() ; PairingServer.Close() ;
The API has three primary functions:
RefreshLocalOobData() - This function causes the Bluetooth controller to generate new hash and randomizer values for the local device. To retrieve the new values call ReadLocalOobData()
ReadLocalOobData() - This function returns the hash and randomizer values that the Bluetooth controller is currently using.
ProvideRemoteOobData() - Use this function to pass OOB data about a remote device to the Bluetooth sub-system. Three versions of the function are available which take slightly different parameters. Information provided using one of these functions can be cleared using ClearRemoteOobData().
Introduction
Dedicated bonding is intended for applications which bond with a specific Bluetooth device.
Using the dedicated bonding API
#include <pairing.h> RBluetoothPairingServer pairingServer ; RBluetoothDedicatedBondingInitiator bonder ; TBTDevAddr addr ; TRequstStatus status ; // Connect to the Pairing server TInt err = pairingServer.connect() ; // Use the Bluetooth address of the remote device bonder.Start( pairingServer, addr, status ) ; // Wait for the request to complete User::WaitForRequest(status); // Close the connection with the bonder (Must be closed before bonding with another device) bonder.Close(); pairingServer.Close() ;