diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/physicallinks.cpp --- a/bluetooth/btstack/linkmgr/physicallinks.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/linkmgr/physicallinks.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -384,49 +384,12 @@ // Store the result of the retrieval for usage later. iDeviceResult = aResult; - // the HW asked earlier for a link key - we can respond now - __ASSERT_DEBUG(iDevice.IsValidAddress(), Panic(EBTPhysicalLinksInvalidAddress)); - if(iWaitingForLinkKeyFromRegistry) + if (iLinkKeyRequestOutstanding) { - if (aResult == KErrNone && iDevice.IsValidLinkKey()) - { - if ( iDevice.LinkKeyType() != ELinkKeyCombination) - { - if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug) - { - LOG(_L("CPhysicalLink: Debug mode - Link to debug link key")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); - } - else - if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable()) - { - LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); - } - else - { - LOG(_L("CPhysicalLink: Issuing link key to HC now")) - iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); - } - } - else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled) - { - LOG(_L("CPhysicalLink: Issuing link key to HC now")) - iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); - } - else - { - LOG(_L("CPhysicalLink: Current PIN code too short!")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); - } - } - else - { - iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); - } + // the HW asked earlier for a link key - we can respond now + __ASSERT_DEBUG(iDevice.IsValidAddress(), Panic(EBTPhysicalLinksInvalidAddress)); + LinkKeyRequestResponseAttempt(ETrue); } - iRequireAuthenticatedLinkKey = EFalse; - iWaitingForLinkKeyFromRegistry = EFalse; RegistryTaskComplete(aHelper, aResult); // cleans up our helper } @@ -546,6 +509,10 @@ iDevice.SetPassKey(iNewPinCode); } + if (iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address())) + { + iLinkKeyObtainedThroughDedicatedBonding = ETrue; + } SetLinkKey(aLinkKey, linkKeyType); // keeps a copy in our 'cache', updates paired list in PHYs mananger @@ -609,7 +576,10 @@ } if(iDevice.IsValidLinkKey() && !iPreventLinkKeyUpdateReg) { - if(!(iIOCapsReceived && (iAuthenticationRequirement == EMitmNotReqNoBonding || iAuthenticationRequirement == EMitmReqNoBonding))) + // We store the link key if it was obtained through dedicated bonding, even if the remote device indicated "no bonding" + // This fixes issues with a lot of remote stacks, and we'll let the UI delete the link key if they want to. + if(iLinkKeyObtainedThroughDedicatedBonding || + !(iIOCapsReceived && (iAuthenticationRequirement == EMitmNotReqNoBonding || iAuthenticationRequirement == EMitmReqNoBonding))) { LOG(_L("!!! Storing Link Key in Registry")); device.SetLinkKey(iDevice.LinkKey(), iDevice.LinkKeyType()); @@ -708,15 +678,9 @@ } else { - // If the remote doesn't support extended features, then neither they support SSP - // (no way to indicate the host supported bit). So set it as disabled. - TPhysicalLinkSimplePairingMode previousSetting = SimplePairingMode(); - __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); - iSimplePairingMode = EPhySimplePairingDisabled; - if(SimplePairingMode() != previousSetting) - { - iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); - } + // If the remote doesn't support extended features, then they cannot support SSP + // (no way to indicate the host supported bit). So set feature as disabled. + RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled); } } else @@ -740,18 +704,12 @@ if (aErr == EOK && aBitMask & (1 << ESecureSimplePairingHostSupportBit) && iLinksMan.SecMan().LocalSimplePairingMode()) { - __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); - iSimplePairingMode = EPhySimplePairingEnabled; + RemoteSimplePairingModeDetermined(EPhySimplePairingEnabled); } else { - __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); - iSimplePairingMode = EPhySimplePairingDisabled; + RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled); } - if(SimplePairingMode()!=currentSetting) - { - iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); - } break; } default: @@ -908,6 +866,7 @@ TRAP(err, iLinksMan.HCIFacade().AuthenticateL(Handle())); if(err == KErrNone) { + iLinkKeyReturnedInThisAuthentication = EFalse; SetAuthenticationPending(EAuthenticationRequestPending); } } @@ -2835,18 +2794,19 @@ SetAuthenticationPending(EPinRequestPending); // if not already set (because the remote initiated authentication). - __ASSERT_DEBUG(iSimplePairingMode != EPhySimplePairingEnabled, Panic(EBTSSPModeChangedDuringConnection)); - if (iSimplePairingMode == EPhySimplePairingUndefined) - { - iSimplePairingMode = EPhySimplePairingDisabled; - } - if (!IsConnected()) { - iPeerInSecurityMode3 = ETrue; + // If the ACL to the peer device is not yet connected, and the peer has initiated + // authentication then it must be in security mode 3. This information is stored and + // if the connection completes the link will be set as authenticated. + SetPeerInSecurityMode3(); } - + // We can receive "fast" PIN requests if the remote device initiates pairing and indicates + // it doesn't have a link key. If we see this then we know that we are not engaging in + // simple pairing on this particular link. + RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled); + if (iPinRequester) { return; @@ -2989,6 +2949,12 @@ || iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address()); } +TBool CPhysicalLink::IsPairingExpected() const + { + LOG_FUNC + return !(IsAuthenticationPending() && iLinkKeyReturnedInThisAuthentication); + } + void CPhysicalLink::DeleteLinkKeyL() /** ensure that the LinkKey is removed from the device in the registry @@ -3056,9 +3022,14 @@ return isPasskeyMinLengthOK; } -void CPhysicalLink::LinkKeyRequest(const TBTDevAddr& aAddr, MLinkKeyResponseHandler& /*aRequester*/) +void CPhysicalLink::LinkKeyRequest(const TBTDevAddr& __DEBUG_ONLY(aAddr), MLinkKeyResponseHandler& /*aRequester*/) { LOG_FUNC + __ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress)); + ASSERT_DEBUG(!iLinkKeyRequestOutstanding); + + iLinkKeyRequestOutstanding = ETrue; + // we don't keep a copy of the device record - we just leave the one copy with // the baseband - it can tell us if there's a link key // we can tell if the baseband has the device record or not @@ -3070,68 +3041,13 @@ // if the connection completes the link will be set as authenticated. if (!IsConnected()) { - iPeerInSecurityMode3 = ETrue; - } - - if(!iPeerInSecurityMode3 && iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address())) - { - // If we are doing DedicatedBonding then we should ignore the existing linkkey - // in an attempt to generate a stronger one if possible. - // Security mode 3 is a odd case - because we get what looks like double pairing (the remote - // initiated pairing on connection, then the dedicated bonding pairing). So we have removed - // this feature for security mode 3 devices...they will have to suffer for their transgressions - LOG(_L("CPhysicalLink: Dedicated bonding attempt - Sending link key request negative reply")); - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - iRequireAuthenticatedLinkKey = EFalse; + SetPeerInSecurityMode3(); } - else if (iDeviceResult==KErrNone && iDevice.IsValidLinkKey()) - { - if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug) - { - LOG(_L("CPhysicalLink: Debug mode - Link to debug link key")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - } - else - { - if (iDevice.LinkKeyType() != ELinkKeyCombination) - { - if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable()) - { - LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - } - else - { - LOG(_L("CPhysicalLink: Issuing link key to HC now")) - iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey()); - } - } - else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled) - { - LOG(_L("CPhysicalLink: Issuing link key to HC now")) - iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey()); - } - else - { - LOG(_L("CPhysicalLink: Current PIN code too short!")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - } - } - iRequireAuthenticatedLinkKey = EFalse; + + if (iLinkKeyRequestOutstanding) + { // might have already been called via SetPeerInSecurityMode3() + LinkKeyRequestResponseAttempt(); } - else if (iDeviceResult==KErrNone && !iDevice.IsValidLinkKey() || iDeviceResult==KErrNotFound) - { - LOG(_L("CPhysicalLink: No Link key available for the device")); - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - iRequireAuthenticatedLinkKey = EFalse; - } - else - { - LOG(_L("CPhysicalLink: Waiting for link key from Registry!")) - // we're still waiting for the device....we'll respond when it turns up - iWaitingForLinkKeyFromRegistry = ETrue; - } - } TInt CPhysicalLink::PINCodeRequestReply(const TBTDevAddr& aDevAddr, const TDesC8& aPin) const @@ -3613,16 +3529,11 @@ iOOBDataPresence = aOOBDataPresence; iAuthenticationRequirement = aAuthenticationRequirement; - //If we haven't determined the SSP pairing mode till now then enable it and notify the state m/c. - //This condition is to cater the fast remote device which responds very quickly, - //even before we determine whether it supports simple pairing!*/ - __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); - if(SimplePairingMode() == EPhySimplePairingUndefined) - { - //Since we have received a I/O cap response the simple pairing must be enabled - iSimplePairingMode = EPhySimplePairingEnabled; - iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); - } + // If we haven't determined the SSP pairing mode the link is operating in yet then enable it, + // since we have received a I/O cap response the simple pairing must be enabled. + // This condition is to cater the fast remote device which responds very quickly, + // even before we determine whether it supports simple pairing! + RemoteSimplePairingModeDetermined(EPhySimplePairingEnabled); } @@ -3751,12 +3662,175 @@ iPasskeyEntry->KeyPressed(aKey); } +void CPhysicalLink::NewUserConfirmerL(const TBTDevAddr aAddr, + CBTSecMan& aSecMan, + TBool aInternallyInitiated) + { + LOG_FUNC + __ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress)); + iUserConfirmer = CBTUserConfirmer::NewL(aAddr, aSecMan, aInternallyInitiated); + } + +CBTUserConfirmer* CPhysicalLink::InstanceUserConfirmer() const + { + LOG_FUNC + return iUserConfirmer; + } + +TBool CPhysicalLink::IsUserConfirmerActive()const + { + LOG_FUNC + return iUserConfirmer->IsActive(); + } + +void CPhysicalLink::DeleteUserConfirmer() + { + LOG_FUNC + delete iUserConfirmer; + iUserConfirmer = NULL; + } + +void CPhysicalLink::CancelUserConfirmer() + { + LOG_FUNC + iUserConfirmer->Cancel(); + } + TBasebandTime CPhysicalLink::GetSniffInterval() const { return iSniffInterval; } +void CPhysicalLink::LinkKeyRequestResponseAttempt(TBool aForceResponse) + { + ASSERT_DEBUG(iLinkKeyRequestOutstanding); + + if(!iPeerInSecurityMode3 && iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address())) + { + // If we are doing DedicatedBonding then we should ignore the existing linkkey + // in an attempt to generate a stronger one if possible. + // Security mode 3 is a odd case - because we get what looks like double pairing (the remote + // initiated pairing on connection, then the dedicated bonding pairing). So we have removed + // this feature for security mode 3 devices...they will have to suffer for their transgressions + LOG(_L("CPhysicalLink: Dedicated bonding attempt - Sending link key request negative reply")); + DoLinkKeyResponse(EFalse); + iRequireAuthenticatedLinkKey = EFalse; + } + else if (iDeviceResult==KErrNone && iDevice.IsValidLinkKey()) + { + if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug) + { + LOG(_L("CPhysicalLink: Debug mode - Link to debug link key")) + DoLinkKeyResponse(EFalse); + } + else if (iDevice.LinkKeyType() != ELinkKeyCombination) + { + if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable()) + { + LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated")) + DoLinkKeyResponse(EFalse); + } + else + { + LOG(_L("CPhysicalLink: non - combination key, auth OK")) + DoLinkKeyResponse(ETrue); + } + } + else // Standard (legacy) Combination Key + { + if (SimplePairingMode() == EPhySimplePairingUndefined) + { + LOG(_L("CPhysicalLink: Waiting for Secure Simple Pairing mode to be determined")); + // wait for ssp mode to be determined...then try again + } + else if (IsPasskeyMinLengthOK() && SimplePairingMode() == EPhySimplePairingDisabled) + { + LOG(_L("CPhysicalLink: Combination key, Passkey len OK, no SSP")); + DoLinkKeyResponse(ETrue); + } + else + { + LOG(_L("CPhysicalLink: Current link key is not sufficient!")) + DoLinkKeyResponse(EFalse); + } + } + iRequireAuthenticatedLinkKey = EFalse; + } + else if (iDeviceResult==KErrNone && !iDevice.IsValidLinkKey() || iDeviceResult==KErrNotFound) + { + LOG(_L("CPhysicalLink: No Link key available for the device")); + DoLinkKeyResponse(EFalse); + iRequireAuthenticatedLinkKey = EFalse; + } + else if (aForceResponse) + { + LOG(_L("CPhysicalLink: Forcing a link key response (-ve as we don't have a link key yet)")); + DoLinkKeyResponse(EFalse); + } + else + { + LOG(_L("CPhysicalLink: Waiting for link key from Registry!")) + // we're still waiting for the device....we'll respond when it turns up + } + } + +/** +Send a link key response for an outstanding request, assumes that all details +have be validated. +*/ +void CPhysicalLink::DoLinkKeyResponse(TBool aPositive) + { + LOG_FUNC + ASSERT_DEBUG(iLinkKeyRequestOutstanding); + + if(aPositive) + { + LOG(_L("CPhysicalLink: Providing link key to HC...")) + ASSERT_DEBUG(iDevice.IsValidLinkKey()); + if (IsAuthenticationPending()) + { + iLinkKeyReturnedInThisAuthentication = ETrue; + } + iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); + } + else + { + LOG(_L("CPhysicalLink: Indicating no link key to HC...")); + iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); + } + iLinkKeyRequestOutstanding = EFalse; + } + +void CPhysicalLink::RemoteSimplePairingModeDetermined(TPhysicalLinkSimplePairingMode aSimplePairingMode) + { + LOG2(_L8("Current SimplePairingMode = %d, aSimplePairingMode = %d"), SimplePairingMode(), aSimplePairingMode); + ASSERT_DEBUG(aSimplePairingMode != EPhySimplePairingUndefined); // must be a definite value + __ASSERT_DEBUG(SimplePairingMode() == aSimplePairingMode || SimplePairingMode() == EPhySimplePairingUndefined, Panic(EBTSSPModeChangedDuringConnection)); + + const TPhysicalLinkSimplePairingMode previousSetting = iSimplePairingMode; + iSimplePairingMode = aSimplePairingMode; + if (previousSetting != iSimplePairingMode) + { + iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); + + // Also we may be waiting to respond to a link key request. + if (iLinkKeyRequestOutstanding) + { + LinkKeyRequestResponseAttempt(); + } + } + } + +void CPhysicalLink::SetPeerInSecurityMode3() + { + iPeerInSecurityMode3 = ETrue; + + // We also now know that the remote cannot possibly do SSP, *and* the LMP will + // likely lock our finding if the remote does SSP anyway while we do SM3. + RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled); + } + // // TLowPowModeCmdController //