--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gba/gbaserver/src/bootstrap.cpp Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,1644 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of bootstrap functions
+*
+*/
+
+
+// This component has the following responsibilities
+// 1. Allow configuration of the BSF URL
+// 2. Open http connection to bsf
+// 3. On digest auth req get nonce
+// 4. Use this to find RAND AUTN
+// 5. Execute SIM auth, get back SRES, IK,CK
+// 6. return SRES
+// 7. Store keymaterial to a token
+
+#include <imcvcodc.h> //for base64 en/decoding
+#include <ecom.h>
+#include "dataretriever.h"
+#include "bootstrap.h"
+#include "GbaCommon.h"
+#include "GBALogger.h"
+#include "GbaSession.h"
+
+const TInt KKsNAFMaxLength = 128;
+const TInt KStringLength = 80;
+const TInt KMaxLengthIMPI = 255;
+const TInt KMaxLengthNAFID = 255;
+const TInt KMaxLengthBTID = 255;
+const TInt KMaxLengthKs = 32;
+const TInt KMaxLengthRES = 16; //16 bytes for RES
+const TInt KMaxLengthAUTS = 16; //16 bytes for AUTS
+const TInt KMaxLengthEnAUTS = 20;
+const TInt KMaxLengthRAND = 16; //16 bytes for RAND
+const TInt KMaxLengthTimeString = 30 ;
+const TInt KHTTPTagLength = 7;
+const TInt KAlgorithmTybeBufferLength = 32;
+const TInt KBufferSize255 = 255;
+const TInt KVariableIndex0 = 0;
+const TInt KVariableIndex1 = 1;
+const TInt KVariableIndex2 = 2;
+const TInt KVariableIndex3 = 3;
+const TInt KVariableIndex4 = 4;
+const TInt KVariableIndex5 = 5;
+const TInt KVariableIndex6 = 6;
+
+#define GBA_UICC_INTERFACE_IMPLE 0x20029F0F
+#define GBA_SOFTISIM_INTERFACE_IMPLE 0x20029F0E
+
+// XML tags
+_LIT8(KBTIDFlag,"<btid>");
+_LIT8(KBTIDEndFlag,"</btid>");
+_LIT8(KLifetimeFlag,"<lifetime>");
+_LIT8(KLifetimeEndFlag,"</lifetime>");
+_LIT(KGbaCredentialsFileName, "GbaCredentials.dat");
+_LIT(KGBAStoreStandardDrive, "C:");
+_LIT(KTimeFormat, "time %d,%d,%d,%d,%d,%d");
+_LIT(KErrorMessage, "FAILED error = %d");
+_LIT(Kakav1, "akav1");
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::NewL()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrap* C3GPPBootstrap::NewL( CGbaServerSession* aSession )
+ {
+ C3GPPBootstrap* self = NewLC( aSession );
+ CleanupStack::Pop(self);
+ return(self) ;
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::NewLC()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrap* C3GPPBootstrap::NewLC( CGbaServerSession* aSession )
+ {
+ C3GPPBootstrap* self = new (ELeave) C3GPPBootstrap( aSession );
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::~C3GPPBootstrap()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrap::~C3GPPBootstrap()
+ {
+ REComSession::DestroyedImplementation(iDtorIDKey);
+ if(IsActive())
+ Cancel();
+ if( iSmartCardInterface )
+ {
+ iSmartCardInterface->Release();
+ REComSession::FinalClose();
+ }
+ delete iKsNAF;
+ delete iNAFID;
+ delete iRand;
+ delete iBTID;
+ delete iIdentity;
+ delete iMasterKey;
+ delete iDataRetriever;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::ConstructL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrap::ConstructL()
+ {
+ GBA_TRACE_BEGIN();
+
+ GBA_TRACE_DEBUG(("initializing buffers"));
+ iKsNAF = HBufC8::NewL(KKsNAFMaxLength);
+ iBTID = HBufC8::NewL(KMaxLengthBTID);
+ iNAFID = HBufC8::NewL(KMaxLengthNAFID);
+ iIdentity = HBufC8::NewL(KMaxLengthIMPI);
+ iMasterKey = HBufC8::NewL(KMaxLengthKs);
+ iRand = HBufC8::NewL(KMaxLengthRAND);
+
+ GBA_TRACE_DEBUG(("initializing http handler"));
+ iDataRetriever = CDataRetriever::NewL( this );
+
+ iImplementationUID.iUid = GBA_UICC_INTERFACE_IMPLE;
+ //if want softisim for testing
+ //iImplementationUID.iUid = GBA_SOFTISIM_INTERFACE_IMPLE;
+
+ //Interface is initialized based on the plug in
+ if ( !IsPluginExistL() )
+ {
+ GBA_TRACE_DEBUG(("There aren't plug-in existing"));
+ User::LeaveIfError( KErrGeneral );
+ }
+
+ GBA_TRACE_DEBUG(("requesting uicc handler"));
+ iSmartCardInterface = RequestUICCInterfaceL();
+ GBA_TRACE_DEBUG(("request made"));
+
+ if ( !iSmartCardInterface )
+ {
+ GBA_TRACE_DEBUG(("Get interface failed"));
+ User::LeaveIfError( KErrGeneral );
+ }
+
+ CActiveScheduler::Add( this );
+
+ GBA_TRACE_END();
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::C3GPPBootstrap()
+// -----------------------------------------------------------------------------
+//
+C3GPPBootstrap::C3GPPBootstrap( CGbaServerSession* aSession ): CActive( EPriorityStandard ),
+ iSmartCardInterface( NULL ), iLifetime ( 0 ),iGBARunType( ENoType ), iBSState(EIdle), iSession ( aSession )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// CBootstrapStateMachine::InitializeL()
+// ---------------------------------------------------------------------------
+//
+void C3GPPBootstrap::InitializeL()
+ {
+ if ( IsActive() )
+ {
+ User::LeaveIfError( KErrInUse );
+ }
+
+ iBSState = EInitialize;
+ GBA_TRACE_DEBUG(("Bootstrapping State machine startL()"));
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+ }
+
+
+// ---------------------------------------------------------------------------
+// C3GPPBootstrap::RunL()
+// ---------------------------------------------------------------------------
+//
+void C3GPPBootstrap::RunL()
+ {
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::RunL() -enter"));
+
+ GBA_TRACE_DEBUG_NUM(("C3GPPBootstrap::RunL iStatus=%d"), iStatus.Int() );
+ GBA_TRACE_DEBUG_NUM(("C3GPPBootstrap::RunL iBSState=%d"), iBSState );
+
+ if((iBSState == ECancel) & iStatus.Int() == KErrCancel)
+ {
+ iBSState = EIdle;
+ return;
+ }
+
+ User::LeaveIfError( iStatus.Int() );
+
+ switch(iBSState)
+ {
+ case EInitialize:
+ {
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::RunL() - EInitialize"));
+ DoBootstrapL();
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::RunL() - EInitialize end"));
+ break;
+ }
+
+ case EBusy:
+ {
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::RunL() - EBusy"));
+ iSession->StateMachineCallBack( iStatus.Int() );
+ Cleanup();
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::RunL() - EBusy end"));
+ break;
+ }
+
+ default:
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::RunL() - default"));
+ break;
+ }
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::RunL() -exit"));
+ }
+
+
+TInt C3GPPBootstrap::RunError(TInt aError)
+ {
+ GBA_TRACE_DEBUG_NUM(("Failed with error = %d"), aError );
+ iSession->StateMachineCallBack( aError );
+ //Back to EBootstrapIdle
+ iBSState = EIdle;
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// C3GPPBootstrap::DoCancel()
+// ---------------------------------------------------------------------------
+//
+void C3GPPBootstrap::DoCancel()
+ {
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::DoCancel()"));
+ switch(iBSState)
+ {
+ case EInitialize:
+ case EBusy:
+ {
+ GBA_TRACE_DEBUG(("C3GPPBootstrap::DoCancel() EBootstrapDone"));
+ CancelBootstrap();
+ break;
+ }
+ default:
+ break;
+ };
+ Cleanup();
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::CancelBootstrap()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrap::CancelBootstrap()
+ {
+ GBA_TRACE_BEGIN();
+ iBSState = ECancel;
+ iDataRetriever->CancelRequest();
+ GBA_TRACE_END();
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::DoBootstrapL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrap::DoBootstrapL( )
+ {
+
+ HBufC8 *BsfUrl = HBufC8::NewLC(KMaxURLLength);
+ TPtr8 PtrBSFUrl( BsfUrl->Des() );
+
+ // fetch bsf address override if available
+ if ( !iSession->Server()->ReadOptionL( KGbaBSFConfiguration, PtrBSFUrl ) )
+ {
+ //If no preset bsf, empty the buffer
+ //We will calculate the address ourselves
+ PtrBSFUrl.Zero();
+ }
+
+ GBA_TRACE_DEBUG((" BSF server address:"));
+ GBA_TRACE_DEBUG( PtrBSFUrl );
+
+ GetBootstrappingMaterialL(
+ PtrBSFUrl,
+ iSession->iGbaInputParams.iNAFName,
+ iSession->iGbaInputParams.iUICCLabel,
+ iSession->iGbaInputParams.iFlags,
+ iSession->iGbaInputParams.iProtocolIdentifier,
+ iSession->iGbaOutputParams.iKNAF,
+ iSession->iGbaOutputParams.iBTID,
+ iSession->iGbaOutputParams.iLifetime,
+ iSession->iGbaOutputParams.iGbaRunType,
+ iSession->iGbaInputParams.iAPID );
+
+ GBA_TRACE_DEBUG(("Bootstrap Request is sent out, let us wait for callback "));
+
+ CleanupStack::PopAndDestroy( BsfUrl );
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::GetBootstrappingMaterialL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrap::GetBootstrappingMaterialL(
+ const TDesC8& aBSFAddress,
+ const TDesC8& aNAFURL,
+ const TDesC8& aUICC_LABEL,
+ const TUint8& aFlags,
+ const TDesC8& aKeyUsage,
+ TDes8 &aKsNAF,
+ TDes8 &aBTID,
+ TTime &aLifetime,
+ EGBARunType& aGBARunType,
+ const TInt& aIAPID )
+ {
+ GBA_TRACE_BEGIN();
+ //save the return buffer's pointer. Copy the databack when bootstrapping is done
+ iCallerKsNAFBuf = &aKsNAF;
+ iCallerLifetime = &aLifetime;
+ iCallerBTIDBuf = &aBTID;
+ iCallerGBARunType = &aGBARunType;
+
+ TUriParser8 uriparser;
+
+
+ GBA_TRACE_DEBUG(("the given naf url is:"));
+ GBA_TRACE_DEBUG(aNAFURL);
+
+ //this implementation is used to solve symbian API's problem
+ // when parsing pure ip address
+ if ( (aNAFURL.FindF(KHTTPTag) != KErrNotFound) || (aNAFURL.FindF(KHTTPSTag) != KErrNotFound) )
+ {
+ //the naf url has http tag
+ User::LeaveIfError( uriparser.Parse(aNAFURL) );
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("the naf url has no http tag, add one for parser"));
+ HBufC8* temp = HBufC8::NewL( aNAFURL.Length() + KHTTPTagLength );
+ CleanupStack::PushL(temp);
+ TPtr8 ptrtemp = temp->Des();
+ ptrtemp.Copy( KHTTPTag );
+ ptrtemp.Append(aNAFURL);
+ GBA_TRACE_DEBUG( *temp );
+ User::LeaveIfError( uriparser.Parse( *temp ) );
+ CleanupStack::PopAndDestroy(temp);
+ }
+
+
+ //Calculate the NAFID, NAFID= NAF_FQDN + keyusage
+
+ TPtr8 ptrNAFID = iNAFID->Des();
+ //parse the FQDN out from NAFaddress
+ ptrNAFID.Copy( uriparser.Extract(EUriHost) );
+ ptrNAFID.Append( aKeyUsage );
+
+ GBA_TRACE_DEBUG(("NAF ID ="));
+ GBA_TRACE_DEBUG(*iNAFID);
+
+
+ GBA_TRACE_DEBUG(("UICC label is:"));
+ GBA_TRACE_DEBUG(aUICC_LABEL);
+
+ // Get IMPI
+ TPtr8 ptrIdentity = iIdentity->Des();
+ //Clean the buffer and Set Length to 0
+ ptrIdentity.Zero();
+
+ //get the IMPI from smart card
+ iSmartCardInterface->QueryIdentityL(ptrIdentity);
+
+ GBA_TRACE_DEBUG(("IMPI is:"));
+ GBA_TRACE_DEBUG( *iIdentity );
+
+ // Get GBA_U availability
+ // EFalse means the call is not from gba client directly.
+ iGBAUAvailable = CheckGBAUAvailabilityL( EFalse );
+
+
+ if ( iGBAUAvailable )
+ {
+ GBA_TRACE_DEBUG(("GBA-U is available"));
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("GBA-U is not available"));
+ }
+
+ // Load Credentails from store.
+ // First compare the IMPI and key lifetime
+ // If IMPI is different or key expires, then return EFalse to
+ // start a new bootstrapping.
+
+ // If IMPI & key lifetime checking both ok,
+ // GBA_U will load B-TID and key lifetime and ask smart card to
+ // calculate the Ks_NAF
+ // GBA_ME will load Ks, Rand, B-TId and key lifetime and calculate it
+ // by ourselves.
+
+ // The GBA run type is also taken from cached store
+
+ if( !(aFlags & EGBAForce) && LoadCredentialsL() )
+ {
+ GBA_TRACE_DEBUG(("Still ok ???"));
+ iStatus = KRequestPending;
+ SetActive();
+ iBSState = EBusy;
+ TRequestStatus* callerStatus = &iStatus;
+ User::RequestComplete(callerStatus, KErrNone);
+ return;
+ }
+
+ // check if the BSF URL was overriden
+ TBuf8<KMaxURLLength> BsfUrl;
+
+ if ( aBSFAddress.Length() == 0 )
+ {
+ GBA_TRACE_DEBUG(("No preset BSF URL, calcuate from IMPI"));
+ iSmartCardInterface->QueryHomeNetworkDnL(BsfUrl);
+ }
+ else
+ {
+ if ( iSmartCardInterface->InterfaceIs2G() )
+ {
+ BsfUrl.Copy( KHTTPSTag );
+ }
+ else
+ {
+ BsfUrl.Copy( KHTTPTag );
+ }
+ BsfUrl.Append( aBSFAddress );
+ }
+
+ GBA_TRACE_DEBUG(("The bsf url is:"));
+ GBA_TRACE_DEBUG(BsfUrl);
+
+ // dataretriever makes the actual http connection to the bsf
+ // when it completes values can be retrieved
+ TUriParser8 uriparser1;
+ User::LeaveIfError( uriparser1.Parse(BsfUrl) );
+
+ iStatus = KRequestPending;
+ SetActive(); // event should come from bootstrapper
+ iBSState = EBusy;
+
+
+ //set reaml as FQDN of bsf
+ iDataRetriever->MakeRequestL( &iStatus, *iIdentity, uriparser1.Extract( EUriHost ), BsfUrl, aNAFURL, aIAPID );
+ GBA_TRACE_END();
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::GBAUAvailabilityL()
+// -----------------------------------------------------------------------------
+//
+TBool C3GPPBootstrap::GBAUAvailabilityL()
+ {
+ //the call is from gba client directly
+ return CheckGBAUAvailabilityL( ETrue );
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::GetState()
+// -----------------------------------------------------------------------------
+//
+TInt C3GPPBootstrap::GetState() const
+ {
+ return iBSState;
+ };
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::CompleteBootStrappingL()
+// This is the callback function called by datareceiver
+// when B-TID and key lifetime is received from BSF
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrap::CompleteBootStrappingL( TInt aError )
+ {
+ // check that we have handler to receive data
+ GBA_TRACE_DEBUG(("C3GPPBootstrapImpl::CompleteBootStrappingL"));
+
+ // Check if triplet auth failed.
+ if ( aError != KErrNone )
+ {
+ GBA_TRACE_DEBUG(("Bootstrap failed"));
+ return;
+ }
+
+ HBufC8* rspbody = iDataRetriever->QueryResponseValueL();
+ if (!rspbody)
+ {
+ GBA_TRACE_DEBUG(("Error no response body"));
+ User::LeaveIfError( KErrGeneral );
+ }
+ CleanupStack::PushL( rspbody );
+ GBA_TRACE_DEBUG(("response body is received. Loaded response:"));
+ GBA_TRACE_DEBUG(*rspbody);
+
+ // make sure it contains a B-TID
+ TInt p = rspbody->FindC(KBTIDFlag);
+ TInt e = rspbody->FindC(KBTIDEndFlag);
+ if ( p != KErrNotFound && e != KErrNotFound)
+ {
+ p += TPtrC8(KBTIDFlag).Length();
+ TInt length = e-p;
+
+ //Copy the B-TID value to caller's buffer
+ //Continue getting Ks_(ext)_NAF
+ iCallerBTIDBuf->Copy(rspbody->Mid(p,length));
+
+ //The B-TID needs to be stored in smart card.
+ //Must save here for later use.
+ TPtr8 ptrBTID = iBTID->Des();
+ ptrBTID.Copy(*iCallerBTIDBuf);
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("Error didn't contain BTID"));
+ CleanupStack::PopAndDestroy(rspbody);
+ User::LeaveIfError( KErrGeneral );
+ }
+
+ GBA_TRACE_DEBUG(("Extracted B-TID:"));
+ GBA_TRACE_DEBUG(*iBTID);
+
+ TBuf8<KMaxLengthTimeString> LifetimeBuf;
+ p = rspbody->FindC(KLifetimeFlag);
+ e = rspbody->FindC(KLifetimeEndFlag);
+ if ( p != KErrNotFound && e != KErrNotFound )
+ {
+ p += TPtrC8(KLifetimeFlag).Length();
+ TInt length = e-p;
+ LifetimeBuf.Copy( rspbody->Mid(p,length) );
+ }
+
+ CleanupStack::PopAndDestroy(rspbody);
+
+ GBA_TRACE_DEBUG(("Lifetime in string:"));
+ GBA_TRACE_DEBUG(LifetimeBuf);
+
+ //Convert the string to TTime object
+ //
+ if ( !ConvertStringToTTime( LifetimeBuf, &iLifetime ) )
+ {
+ GBA_TRACE_DEBUG(("Couldn't convert lifetime"));
+ User::LeaveIfError( KErrGeneral );
+ }
+
+ // Set the lifetime to caller's buffer
+ *iCallerLifetime = iLifetime;
+
+ //After bootstrap is succesful, the B-TID and keylifetime
+ //should be sent back to smart card to store in GBA_U.
+ if ( iGBAUAvailable )
+ {
+ HBufC8* lifetime = HBufC8::NewLC( LifetimeBuf.Length() );
+ TPtr8 lifetimePtr = lifetime->Des();
+ lifetimePtr.Copy( LifetimeBuf );
+ TInt err = iSmartCardInterface->UpdateGBADataL( *iBTID, *lifetime );
+ CleanupStack::PopAndDestroy( lifetime );
+ User::LeaveIfError( err );
+ iGBARunType = EGBAU;
+ }
+ else
+ {
+ if ( iSmartCardInterface->InterfaceIs2G() )
+ {
+ iGBARunType = E2GGBA;
+ }
+ else
+ {
+ iGBARunType = E3GGBAME;
+ }
+ }
+
+ // Set the GBA run type back to caller
+ *iCallerGBARunType = iGBARunType;
+ // cache the new fangled credentials
+ StoreCredentialsL();
+
+ // Generate Key material and copy it to parameter being returned
+ if ( GenerateKeyMaterialL() )
+ {
+
+ if ( iGBAUAvailable )
+ {
+ GBA_TRACE_DEBUG(("It is GBA_U mode,The ks_ext_naf is calculated by smart card"));
+ GBA_TRACE_DEBUG_BINARY( *iKsNAF);
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("It is GBA_ME mode,The ks_naf is calculated by gbamodule"));
+ GBA_TRACE_DEBUG_BINARY( *iKsNAF );
+ GBA_TRACE_DEBUG(("It is GBA_ME mode,The ks_naf is calculated by gbamodule 1"));
+ }
+ //Set KsNAF back to caller's buffer
+ iCallerKsNAFBuf->Copy(*iKsNAF);
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("Error no keys"));
+ User::LeaveIfError( KErrGeneral );
+ }
+ GBA_TRACE_END();
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::GetCredentialsL()
+// function GetCredentialsL
+// discussion: Gets URI, Realm, Nonce and AuthenticationType, and gives back Username and Password.
+// param: :aURI : the address of the bsf.
+// param: :aRealm : the realm of the bsf.
+// param: :aNonce : the nonce sent by the bsf.
+// param: :aAuthenticationType : the authentication type sent by the bsf.
+// param: :aUsername : Generated Username by underlying algorithm (AKA or SIM).
+// param: :aPassword : Generated Password by underlying algorithm (AKA or SIM).
+// result: The result of the operation: true for success and false for failure!
+// -----------------------------------------------------------------------------
+TBool C3GPPBootstrap::GetCredentialsL(const TUriC8& /*aURI*/, RString aRealm, RString aNonce,
+ RString aAlgorithm,
+ RString& aUsername,
+ RString& aPassword,
+ RString& aResync,
+ TBool& aResyncRequired)
+ {
+ GBA_TRACE_BEGIN();
+
+ // smartcard interface returns true if credentials are received
+ TBool GotKeys = EFalse;
+ TInt pushCount = 0;
+
+ HBufC *algType=HBufC::NewLC( KAlgorithmTybeBufferLength );
+ pushCount++;
+
+ TPtr pAlgType(algType->Des());
+ pAlgType.Copy(aAlgorithm.DesC());
+ pAlgType.LowerCase();
+
+ TInt SecurityAlgorithm;
+
+ //AuthenticationType MUST be AKAV1-MD5
+ //Find() function returns the offset of the data sequence from the beginning of
+ //this descriptor's data. KErrNotFound, if the data sequence cannot be found.
+ if ( pAlgType.Find(Kakav1) != KErrNotFound )
+ {
+ GBA_TRACE_DEBUG((" algorithm is akav1"));
+ SecurityAlgorithm = EAKAv1;
+ }
+ else
+ {
+ GBA_TRACE_DEBUG((" algorithm is unknown"));
+ SecurityAlgorithm = ESecAlgUnknown;
+ }
+
+ HBufC8 *nonce = HBufC8::NewLC(KStringLength);
+ pushCount++;
+
+ TPtr8 ptrNonce = nonce->Des();
+ ptrNonce.Copy(aNonce.DesC());
+
+ GBA_TRACE_DEBUG((" The base64 encoded nonce value from BSF server (RAND + AUTN)"));
+ GBA_TRACE_DEBUG(aNonce.DesC());
+ GBA_TRACE_DEBUG((" The base64 encoded nonce value after copying into buffer:"));
+ GBA_TRACE_DEBUG(*nonce);
+
+ //buffer used to store decoded nonce value
+ HBufC8 *decodedNonce = HBufC8::NewLC(KStringLength);
+ pushCount++;
+
+ TPtr8 ptrDecNonce = decodedNonce->Des();
+
+ //fill the buffer with zeros.
+ ptrDecNonce.FillZ();
+
+ // decodes the base64 nonce
+ TImCodecB64 b64coder;
+ b64coder.Initialise();
+ b64coder.Decode( *nonce, ptrDecNonce );
+
+ GBA_TRACE_DEBUG((" The decoded nonce value in binary"));
+ GBA_TRACE_DEBUG_BINARY( *decodedNonce );
+
+ //Allocate buffer RES, password for http digest
+ HBufC8* RES = HBufC8::NewLC( KMaxLengthRES );
+ pushCount++;
+ TPtr8 ptrRES = RES->Des();
+
+ //Allocate buffer AUTS, if the out of sync happens
+ HBufC8* AUTS = HBufC8::NewLC( KMaxLengthAUTS );
+ pushCount++;
+ TPtr8 ptrAUTS = AUTS->Des();
+
+ GBA_TRACE_DEBUG((" check algorithm value"));
+ switch (SecurityAlgorithm)
+ {
+ case EAKAv1:
+ {
+ GBA_TRACE_DEBUG((" EAKAv1"));
+ aResyncRequired = EFalse;
+ //Set the RAND AUTN to smart card
+ GotKeys = iSmartCardInterface->QueryAuthenticationL( *decodedNonce, ptrRES, ptrAUTS );
+
+ TBool AUTSBufEmpty = EFalse;
+
+ // No out of sync detected
+ if ( GotKeys || AUTS->Length() == 0 )
+ {
+ GBA_TRACE_DEBUG(("AUTS is not returned. No out of sync detected"));
+ AUTSBufEmpty = ETrue;
+ }
+
+ if ( !GotKeys && !AUTSBufEmpty && AUTS->Length()>0 )
+ {
+ aResyncRequired = ETrue;
+ GBA_TRACE_DEBUG(("AUTS is returned. Resync is required"));
+ GBA_TRACE_DEBUG_BINARY(*AUTS);
+ }
+
+ // keep rand
+ // as the first 16 bytes in Nonce as RAND
+ TPtr8 ptrRand = iRand->Des();
+ ptrRand.Copy( ptrDecNonce.Left(KMaxLengthRAND) );
+
+ GBA_TRACE_DEBUG(("RAND is:"));
+ GBA_TRACE_DEBUG_BINARY(*iRand);
+
+ //if GBA_U is available, we donot need to save the
+ //Ks. It is stored on smart card
+
+ if( GotKeys && !iGBAUAvailable )
+ {
+ // keep master key
+ TPtr8 ptrMasterKey = iMasterKey->Des();
+ if ( !iSmartCardInterface->QueryKs( ptrMasterKey ) )
+ {
+ User::LeaveIfError( KErrGeneral );
+ }
+ }
+ }
+ break;
+
+ case ESecAlgUnknown:
+ {
+ User::LeaveIfError( KErrArgument );
+ }
+ break;
+
+ default:
+ {
+ User::LeaveIfError( KErrArgument );
+ }
+ break;
+ }
+
+
+ GBA_TRACE_DEBUG(("AKA password RES for BSF"));
+ GBA_TRACE_DEBUG_BINARY( *RES );
+
+ // if received keys or auts then we can attempt to authenticate towards the BSF
+ // is this code setting the password? Password should be the RES or empty
+
+ if ( aResyncRequired )
+ //AUTS returned
+ {
+ _LIT8(KEmptyPwd,"");
+ aPassword = aRealm.Pool().OpenStringL(KEmptyPwd);
+ }
+
+ if(GotKeys)
+ {
+ //Set RES as password
+ TRAPD( err,aPassword = aRealm.Pool().OpenStringL(*RES) );
+ err = err;
+ GBA_TRACE_DEBUG_NUM((" Set RES as password error %d"), err );
+ }
+
+ //Set IMPI as username
+ aUsername = aRealm.Pool().OpenStringL(iIdentity->Des());
+
+ // convert received auts into a string
+ if ( aResyncRequired )
+ {
+ GBA_TRACE_DEBUG(("adding auts to the headers"));
+ HBufC8 *encodedAUTS = HBufC8::NewLC( KMaxLengthEnAUTS );
+ pushCount++;
+ TPtr8 ptrEncAUTS = encodedAUTS->Des();
+ ptrEncAUTS.FillZ();
+
+ b64coder.Encode( *AUTS, ptrEncAUTS );
+
+ GBA_TRACE_DEBUG(*encodedAUTS);
+
+ aResync = aRealm.Pool().OpenStringL(*encodedAUTS);
+ }
+
+ CleanupStack::PopAndDestroy(pushCount);
+ GBA_TRACE_END();
+ return GotKeys;
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::GenerateKeyMaterialL()
+// -----------------------------------------------------------------------------
+TBool C3GPPBootstrap::GenerateKeyMaterialL()
+ {
+ TPtr8 derivedKey(iKsNAF->Des());
+
+ if ( iGBAUAvailable )
+ {
+ iSmartCardInterface->QueryKeyMaterialL(
+ KNullDesC8,
+ KNullDesC8,
+ iIdentity->Des(),
+ *iNAFID,
+ derivedKey
+ );
+ return ETrue;
+ }
+ else
+ {
+ iSmartCardInterface->QueryKeyMaterialL(
+ iMasterKey->Des(),
+ iRand->Des(),
+ iIdentity->Des(),
+ *iNAFID,
+ derivedKey
+ );
+ return ETrue;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::Cleanup()
+// -----------------------------------------------------------------------------
+void C3GPPBootstrap::Cleanup()
+ {
+ GBA_TRACE_DEBUG(("Enter "));
+ iBSState = EIdle;
+ iGBAUAvailable = EFalse;
+ iGBARunType = ENoType;
+
+ iKsNAF->Des().Zero();
+ iBTID->Des().Zero();
+ iLifetime = 0;
+
+ iIdentity->Des().Zero(); //buffer for impi
+ iNAFID->Des().Zero(); //buffer for nafid
+ iRand->Des().Zero(); //buffer for rand
+ iMasterKey->Des().Zero(); //buffer for Ks
+ GBA_TRACE_DEBUG(("Exit "));
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::LoadCredentials()
+// GBA_ME, load the cached credentails to calculate ks_naf
+// -----------------------------------------------------------------------------
+TBool C3GPPBootstrap::LoadCredentialsL()
+ {
+ GBA_TRACE_DEBUG(("Enter "));
+ TBool result = EFalse;
+
+ // check if the values are in memory
+ // IsStillValid needs to be implemented
+ //if( iMasterKey && IsStillValid( &iLifetime ))
+ //{
+ //GBA_TRACE_DEBUG(("using the Ks in memory"));
+ //return ETrue;
+ //}
+
+ GBA_TRACE_DEBUG(("Checking if the credtials are stored"));
+
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ CleanupClosePushL(fs);
+ TFindFile folder( fs );
+
+ TFileName fullPath;
+
+ MakePrivateFilenameL(fs, KGbaCredentialsFileName, fullPath);
+ GBA_TRACE_DEBUG(fullPath);
+
+ TInt err = folder.FindByDir( fullPath, KNullDesC);
+
+ if ( err != KErrNone )
+ {
+ GBA_TRACE_DEBUG(("No credentials store available"));
+ CleanupStack::PopAndDestroy(&fs);
+ return result;
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("Found credentials store "));
+ CDictionaryFileStore* pStore = CDictionaryFileStore::OpenLC(fs,fullPath,KUidGBACredRoot);
+
+ TInt length = 0;
+ HBufC8* tmpIdentity = NULL;
+
+ //Read IMPI
+ if ( pStore->IsPresentL( KUidIMPI ) )
+ {
+ GBA_TRACE_DEBUG(("IMPI is present "));
+ RDictionaryReadStream reader;
+ CleanupClosePushL(reader);
+ reader.OpenL(*pStore,KUidIMPI);
+ length = reader.ReadInt32L();
+ tmpIdentity = HBufC8::NewL(length);
+ TPtr8 ptrtmpIdentity = tmpIdentity->Des();
+
+ reader.ReadL(ptrtmpIdentity,length);
+ GBA_TRACE_DEBUG(("IMPI = "));
+ GBA_TRACE_DEBUG(ptrtmpIdentity);
+ CleanupStack::PopAndDestroy( &reader );
+ }
+
+ //Read ks
+ if ( pStore->IsPresentL( KUidKs ) )
+ {
+ GBA_TRACE_DEBUG(("Ks is present, the cached credentials are from GBA_ME "));
+ GBA_TRACE_DEBUG(("Ks is present "));
+ RDictionaryReadStream reader1;
+ CleanupClosePushL(reader1);
+ reader1.OpenL(*pStore,KUidKs);
+ length = reader1.ReadInt32L();
+
+ TPtr8 ptrmk = iMasterKey->Des();
+ ptrmk.Zero();
+ reader1.ReadL(ptrmk,length);
+ ptrmk.SetLength(length);
+ GBA_TRACE_DEBUG(("Ks = "));
+ GBA_TRACE_DEBUG_BINARY(ptrmk);
+ CleanupStack::PopAndDestroy( &reader1 );
+ }
+
+
+ //Read rand
+ if ( pStore->IsPresentL( KUidRand ) )
+ {
+ GBA_TRACE_DEBUG(("Rand is present "));
+ RDictionaryReadStream reader2;
+ CleanupClosePushL(reader2);
+ reader2.OpenL(*pStore,KUidRand);
+ length = reader2.ReadInt32L();
+
+ TPtr8 ptrRand = iRand->Des();
+ ptrRand.Zero();
+ reader2.ReadL(ptrRand,length);
+ ptrRand.SetLength(length);
+ GBA_TRACE_DEBUG(("Rand = "));
+ GBA_TRACE_DEBUG_BINARY(ptrRand);
+ CleanupStack::PopAndDestroy( &reader2 );
+ }
+
+ //Read BTID
+ if ( pStore->IsPresentL( KUidBTID ) )
+ {
+ GBA_TRACE_DEBUG(("B-TID is present "));
+ RDictionaryReadStream reader3;
+ CleanupClosePushL(reader3);
+ reader3.OpenL(*pStore,KUidBTID);
+ length = reader3.ReadInt32L();
+
+ TPtr8 ptrBTID = iBTID->Des();
+ ptrBTID.Zero();
+ reader3.ReadL(ptrBTID,length);
+ ptrBTID.SetLength(length);
+ GBA_TRACE_DEBUG(("BTID = "));
+ GBA_TRACE_DEBUG(ptrBTID);
+ CleanupStack::PopAndDestroy( &reader3 );
+ }
+
+ //Read key lifetime
+ if ( pStore->IsPresentL( KUidkeylifetime ) )
+ {
+ GBA_TRACE_DEBUG(("key lifetime is present "));
+ RDictionaryReadStream reader4;
+ CleanupClosePushL(reader4);
+ reader4.OpenL(*pStore,KUidkeylifetime);
+ iLifetime = NULL;
+ TPtr8 ptrkeylifetime((TUint8*)&iLifetime,sizeof(TTime));
+
+ reader4.ReadL(ptrkeylifetime,sizeof(TTime));
+ GBA_TRACE_DEBUG(("keylifetime = "));
+ GBA_TRACE_TIME( iLifetime );
+ CleanupStack::PopAndDestroy( &reader4 );
+ }
+
+ //Read GBA run type
+ if ( pStore->IsPresentL( KUidGBARunType ) )
+ {
+ GBA_TRACE_DEBUG(("GBARunType is present "));
+ RDictionaryReadStream reader5;
+ CleanupClosePushL(reader5);
+ reader5.OpenL(*pStore,KUidGBARunType);
+ iGBARunType = (EGBARunType)reader5.ReadInt8L();
+ CleanupStack::PopAndDestroy( &reader5 );
+ }
+
+
+ //done with store
+ CleanupStack::PopAndDestroy( pStore );
+ CleanupStack::PopAndDestroy(&fs);
+
+ result = IsStillValid( &iLifetime ) && *tmpIdentity == *iIdentity;
+
+ //smart card has been changed
+ if ( *tmpIdentity != *iIdentity )
+ {
+ iSmartCardInterface->NotifyCardChangeL();
+ }
+
+ GBA_TRACE_DEBUG(("Cached IMPI = "));
+ GBA_TRACE_DEBUG(*tmpIdentity);
+ GBA_TRACE_DEBUG(("IMPI from smart card = "));
+ GBA_TRACE_DEBUG(*iIdentity);
+
+ // this has served its purpose
+ delete tmpIdentity;
+
+ // if the credentials aren't valid delete the old key
+ if ( !result )
+ {
+ GBA_TRACE_DEBUG(("clean buffers since the key wasn't valid anymore or the card had been changed"));
+ // clean up the created buffers;
+ iMasterKey->Des().Zero();
+ iRand->Des().Zero();
+ iBTID->Des().Zero();
+ iLifetime = NULL;
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("cached keys were still valid"));
+ GBA_TRACE_DEBUG(("Cached B-TID is:"));
+ GBA_TRACE_DEBUG(*iBTID );
+
+ iCallerBTIDBuf->Copy( *iBTID );
+
+ // Set the run type
+ *iCallerGBARunType = iGBARunType;
+
+ //Set key life time
+ *iCallerLifetime = iLifetime;
+
+ // generate material based on the stored credentials
+ if ( GenerateKeyMaterialL() )
+ {
+ if ( iGBAUAvailable )
+ {
+ GBA_TRACE_DEBUG(("Calu from Cached Ks: It is GBA_U mode,The ks_ext_naf is calculated by smart card"));
+ GBA_TRACE_DEBUG_BINARY( *iKsNAF );
+ GBA_TRACE_DEBUG(("Calu test11"));
+
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("Calu from Cached Ks. It is GBA_ME mode,The ks_naf is calculated by gbamodule"));
+ GBA_TRACE_DEBUG_BINARY( *iKsNAF );
+ }
+ //Set KsNAF back to caller's buffer
+ iCallerKsNAFBuf->Copy(*iKsNAF);
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("Error no keys"));
+ result = EFalse;
+ }
+ }
+ GBA_TRACE_DEBUG(("Calu test11"));
+ }
+ return result;
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::StoreCredentialsL()
+// Store bootstrapping credentails into the store
+// GBA_ME: IMPI, Ks, Rand, B-TID, key lifetime
+// GBA_U: IMPI, B-TID, key lifetime
+// -----------------------------------------------------------------------------
+void C3GPPBootstrap::StoreCredentialsL()
+ {
+ GBA_TRACE_DEBUG(("Save credentials into dictionary store"));
+
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+ TFindFile folder( fs );
+
+ TFileName fullPath;
+
+ MakePrivateFilenameL(fs, KGbaCredentialsFileName, fullPath);
+ EnsurePathL(fs, fullPath );
+
+ GBA_TRACE_DEBUG(fullPath);
+ TInt err = folder.FindByDir( fullPath, KNullDesC );
+
+ if ( err == KErrNotFound || err == KErrNone || err == KErrPathNotFound )
+ {
+
+ CDictionaryFileStore* pStore = CDictionaryFileStore::OpenLC(fs,fullPath,KUidGBACredRoot);
+
+ //Save IMPI
+ RDictionaryWriteStream writer;
+ CleanupClosePushL(writer);
+ writer.AssignL(*pStore, KUidIMPI);
+ writer.WriteInt32L(iIdentity->Size());
+ writer.WriteL(*iIdentity);
+ writer.CommitL();
+ CleanupStack::PopAndDestroy( &writer );
+
+ //GBA_U doesn't need to save ks and rand.
+ if ( !iGBAUAvailable )
+ {
+ GBA_TRACE_DEBUG(("It is GBA_ME, save Ks and Rand"));
+ //Save ks
+ RDictionaryWriteStream writer1;
+ CleanupClosePushL(writer1);
+ writer1.AssignL( *pStore, KUidKs );
+ writer1.WriteInt32L(iMasterKey->Size());
+ writer1.WriteL(*iMasterKey);
+ writer1.CommitL();
+ CleanupStack::PopAndDestroy( &writer1 );
+
+ //Save Rand
+ RDictionaryWriteStream writer2;
+ CleanupClosePushL(writer2);
+ writer2.AssignL(*pStore,KUidRand );
+ writer2.WriteInt32L(iRand->Size());
+ writer2.WriteL(*iRand);
+ writer2.CommitL();
+ CleanupStack::PopAndDestroy( &writer2 );
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("It is GBA_U, remove Ks and Rand if there are"));
+ pStore->RemoveL(KUidKs);
+ pStore->RemoveL(KUidRand);
+ }
+ //Save B-TID
+ RDictionaryWriteStream writer3;
+ CleanupClosePushL(writer3);
+ writer3.AssignL(*pStore,KUidBTID );
+ writer3.WriteInt32L(iBTID->Size());
+ writer3.WriteL(*iBTID);
+ writer3.CommitL();
+ CleanupStack::PopAndDestroy( &writer3 );
+
+ //Save key lifetime
+ RDictionaryWriteStream writer4;
+ CleanupClosePushL(writer4);
+ writer4.AssignL(*pStore,KUidkeylifetime );
+ TPtrC8 ptrkeylifetime((TUint8*)&iLifetime,sizeof(TTime));
+ writer4.WriteL(ptrkeylifetime);
+ writer4.CommitL();
+ CleanupStack::PopAndDestroy( &writer4 );
+
+ //Save gba run type
+ RDictionaryWriteStream writer5;
+ CleanupClosePushL(writer5);
+ writer5.AssignL(*pStore,KUidGBARunType);
+ writer5.WriteInt8L(iGBARunType);
+ writer5.CommitL();
+ CleanupStack::PopAndDestroy( &writer5 );
+
+ pStore->CommitL();
+ CleanupStack::PopAndDestroy( pStore );
+ CleanupStack::PopAndDestroy( &fs );
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy( &fs );
+ User::LeaveIfError( err );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::CheckGBAUAvailability()
+// Check the GBA availability from store, if no record there, check from
+// smart card directly.
+// -----------------------------------------------------------------------------
+TBool C3GPPBootstrap::CheckGBAUAvailabilityL( TBool aIsfromGBAClient )
+ {
+ TBool GBAUAvailability = EFalse;
+ //Read the record from store
+ TInt result = LoadGBAUAvailabililtyFromStoreL( aIsfromGBAClient, GBAUAvailability );
+
+ //The store GBA type is GBA_U or GBA_ME
+ if ( result != KErrNotFound && result != KErrGeneral )
+ {
+ //return the cached GBAU availabilty, since smart card is not changed
+ return GBAUAvailability;
+ }
+ else if ( result == KErrGeneral )
+ {
+ //impi is different
+ //delete the whole store
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ CleanupClosePushL(fs);
+ TFileName fullPath;
+ MakePrivateFilenameL(fs, KGbaCredentialsFileName, fullPath);
+ fs.Delete( fullPath );
+ CleanupStack::PopAndDestroy( &fs );
+ }
+ else
+ {
+ //The first time query
+ }
+ // There is no record on GBA_U availability or impis are different
+ // It only happens on the first time when GBA server starts
+ // or after smart card is removed.
+
+ //retrieve the GBA availability from smart card
+ iSmartCardInterface->QueryGBAUAvailabilityL( GBAUAvailability );
+
+ SaveGBAUAvailabilityToStoreL( GBAUAvailability );
+ return GBAUAvailability;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::LoadGBAUAvailabililtyFromStoreL()
+// -----------------------------------------------------------------------------
+TInt C3GPPBootstrap::LoadGBAUAvailabililtyFromStoreL( TBool& aIsfromGBAClient, TBool& aGBAUAvail )
+ {
+ GBA_TRACE_DEBUG(("Loading the GBA-U avail from store"));
+ TInt cleanupstack = 0;
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ CleanupClosePushL(fs);
+ cleanupstack++;
+ TFindFile folder( fs );
+
+
+ TFileName fullPath;
+ MakePrivateFilenameL(fs, KGbaCredentialsFileName, fullPath);
+ GBA_TRACE_DEBUG(fullPath);
+ TInt err = folder.FindByDir( fullPath, KNullDesC );
+
+ // the store file is not available
+ if ( err != KErrNone )
+ {
+ GBA_TRACE_DEBUG(("No store available"));
+ CleanupStack::PopAndDestroy(cleanupstack);
+
+ //get impi here, save to store later
+ if ( aIsfromGBAClient )
+ {
+ //retrieve the impi from smart card
+ TPtr8 idPtr = iIdentity->Des();
+ idPtr.Zero();
+ TRAPD(error,iSmartCardInterface->QueryIdentityL(idPtr));
+
+ if( error != KErrNone )
+ {
+ GBA_TRACE_DEBUG((" Can't get IMPI from smart card"));
+ User::LeaveIfError( error );
+ }
+
+ GBA_TRACE_DEBUG((" got IMPI"));
+ }
+ return KErrNotFound;
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("Found store "));
+ CDictionaryFileStore* pStore = CDictionaryFileStore::OpenLC(fs,KGbaCredentialsFileName,KUidGBACredRoot);
+ cleanupstack++;
+ TInt impiLength = 0;
+ HBufC8* cachedimpi = NULL;
+ TInt8 GBAUAvail = 0;
+
+ //Read GBA-U avail
+ if ( pStore->IsPresentL( KUidGBAUAvail ) )
+ {
+ GBA_TRACE_DEBUG(("GBAU Avail is present "));
+ RDictionaryReadStream reader;
+ CleanupClosePushL(reader);
+ reader.OpenL(*pStore,KUidGBAUAvail);
+ GBAUAvail = reader.ReadInt8L();
+ CleanupStack::PopAndDestroy( &reader );
+ }
+
+ //Read IMPI
+ if ( pStore->IsPresentL( KUidIMPI ) )
+ {
+ GBA_TRACE_DEBUG(("IMPI is present "));
+ RDictionaryReadStream reader1;
+ CleanupClosePushL(reader1);
+ cleanupstack++;
+ reader1.OpenL(*pStore,KUidIMPI);
+ impiLength = reader1.ReadInt32L();
+
+ cachedimpi = HBufC8::NewLC(impiLength);
+ cleanupstack++;
+ TPtr8 ptrcachedimpi = cachedimpi->Des();
+
+ reader1.ReadL(ptrcachedimpi,impiLength);
+ ptrcachedimpi.SetLength(impiLength);
+ GBA_TRACE_DEBUG(("IMPI = "));
+ GBA_TRACE_DEBUG(ptrcachedimpi);
+
+ if ( aIsfromGBAClient )
+ {
+ //retrieve the impi from smart card
+ TPtr8 idPtr = iIdentity->Des();
+ idPtr.Zero();
+ TRAPD(error,iSmartCardInterface->QueryIdentityL(idPtr));
+
+ if( error != KErrNone )
+ {
+ GBA_TRACE_DEBUG((" Can't get IMPI from smart card"));
+ User::LeaveIfError( error );
+ }
+
+ GBA_TRACE_DEBUG((" got IMPI"));
+ }
+
+
+ if( *iIdentity == *cachedimpi )
+ {
+ GBA_TRACE_DEBUG(("IMPI are the same"));
+ //the impi are the same, return the cached gbau availability
+ CleanupStack::PopAndDestroy(cleanupstack);
+ aGBAUAvail = (TBool)GBAUAvail;
+ return KErrNone;
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("IMPIs are different"));
+ //the impi are different, return KErrGeneral
+ iSmartCardInterface->NotifyCardChangeL();
+ CleanupStack::PopAndDestroy(cleanupstack);
+ return KErrGeneral;
+ }
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("no impi present"));
+ return KErrGeneral;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::SaveGBAUAvailabilityToStoreL()
+// -----------------------------------------------------------------------------
+//
+void C3GPPBootstrap::SaveGBAUAvailabilityToStoreL( TBool& aGBAUAvail )
+ {
+ GBA_TRACE_DEBUG(("Save GBA-U avail into dictionary store"));
+
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+ TFindFile folder( fs );
+
+ TFileName fullPath;
+ MakePrivateFilenameL(fs, KGbaCredentialsFileName, fullPath);
+ EnsurePathL(fs, fullPath );
+ GBA_TRACE_DEBUG(fullPath);
+ TInt err = folder.FindByDir( fullPath, KNullDesC );
+
+ if ( err == KErrNotFound || err == KErrNone || err == KErrPathNotFound )
+ {
+
+ CDictionaryFileStore* pStore = CDictionaryFileStore::OpenLC(fs,fullPath,KUidGBACredRoot);
+
+ //Save IMPI
+ RDictionaryWriteStream writer;
+ CleanupClosePushL(writer);
+ writer.AssignL(*pStore, KUidIMPI);
+ writer.WriteInt32L(iIdentity->Size());
+ writer.WriteL(*iIdentity);
+ writer.CommitL();
+ CleanupStack::PopAndDestroy( &writer );
+ //Save GBA-U avail
+ RDictionaryWriteStream writer1;
+ CleanupClosePushL(writer1);
+ writer1.AssignL(*pStore,KUidGBAUAvail );
+ writer1.WriteInt8L((TInt8)aGBAUAvail);
+ writer1.CommitL();
+ CleanupStack::PopAndDestroy( &writer1 );
+
+ pStore->CommitL();
+ CleanupStack::PopAndDestroy(pStore);
+ CleanupStack::PopAndDestroy(&fs);
+ GBA_TRACE_DEBUG(("Save GBA-U avail successfully"));
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("Save GBA-U avail failed"));
+ CleanupStack::PopAndDestroy(&fs);
+ User::LeaveIfError( err );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::IsStillValid()
+// -----------------------------------------------------------------------------
+//
+TBool C3GPPBootstrap::IsStillValid( TTime* aLifetime )
+ {
+ TTime nowTime;
+ nowTime.UniversalTime();
+ GBA_TRACE_DEBUG(("Current Time:"));
+ GBA_TRACE_TIME( nowTime );
+
+ GBA_TRACE_DEBUG(("Expiry Time:"));
+ GBA_TRACE_TIME( *aLifetime );
+
+ if( *aLifetime > nowTime )
+ {
+ GBA_TRACE_DEBUG(("key still valid"));
+ return ETrue;
+ }
+ else
+ {
+ GBA_TRACE_DEBUG(("key expired"));
+ return EFalse;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3GPPBootstrap::ConvertStringToTTime()
+// -----------------------------------------------------------------------------
+//
+TBool C3GPPBootstrap::ConvertStringToTTime(TDesC8& aLifetimeBuf, TTime* aLifetime)
+{
+ GBA_TRACE_BEGIN();
+ TInt aTimeVariable[KVariableIndex6] =
+ {
+ 0,0,0,0,0,0
+ }; // { year,month,day,hour,minute,second }
+
+ // assuming the lifetime is given in ISO 8601 format
+ // YYYY-MM-DD or YYYYMMDD (we don't allow YYYYMM or YYYY format, although this isn't specified in the standard)
+ // (year could have a + before it if key is valid beyond year 9999, but we hope that someone will rewrite this within next 8000 years)
+ // there might be a T between date and time we just ignore it
+ // hours
+ // hh:mm:ss or hhmmss
+ // hh:mm or hhmm
+ // hh
+
+ TInt pos = 0;
+ TInt len = KVariableIndex4;
+ for(TInt variableIndex = 0; variableIndex < KVariableIndex6; variableIndex++)
+ {
+ // if next value isn't a digit we're done
+ if(!TChar(aLifetimeBuf[pos]).IsDigit())
+ break;
+
+ if(pos + len < aLifetimeBuf.Length())
+ {
+
+ TLex8 lex(aLifetimeBuf.Mid(pos,len));
+ if(KErrNone != lex.Val(aTimeVariable[variableIndex]))
+ {
+ GBA_TRACE_DEBUG(("failed"));
+ GBA_TRACE_DEBUG(aLifetimeBuf.Mid(pos,len));
+ return EFalse;
+ }
+ pos += len;
+
+
+ // remove possible separators
+ if(aLifetimeBuf[pos] == '-' || aLifetimeBuf[pos] == ':')
+ pos += 1;
+ // there can be spaces after month
+ if( variableIndex == KVariableIndex2 )
+ while(pos < aLifetimeBuf.Length() &&
+ (TChar(aLifetimeBuf[pos]).IsSpace() || aLifetimeBuf[pos] == 'T'))
+ pos++;
+
+ }
+ else
+ {
+ // if we don't get second it doesn't matter
+ if(variableIndex >= KVariableIndex5)
+ break;
+ return EFalse;
+ }
+ len = KVariableIndex2; // year is the exception
+ }
+ // Symbian months and days start from 0, UTC months from 1
+ aTimeVariable[1] = aTimeVariable[1] - 1;
+ aTimeVariable[2] = aTimeVariable[2] - 1;
+
+ TBuf<KBufferSize255> aDBBuf;
+ aDBBuf.Format(KTimeFormat, aTimeVariable[KVariableIndex0],aTimeVariable[KVariableIndex1],aTimeVariable[KVariableIndex2],
+ aTimeVariable[KVariableIndex3],aTimeVariable[KVariableIndex4],aTimeVariable[KVariableIndex5]);
+ GBA_TRACE_DEBUG(aDBBuf);
+
+ // time should always be in UTC so no need to check the timezone
+ TDateTime dt;
+
+ TRAPD(error,dt.Set(
+ aTimeVariable[KVariableIndex0],
+ (TMonth)(aTimeVariable[KVariableIndex1]),
+ aTimeVariable[KVariableIndex2],
+ aTimeVariable[KVariableIndex3],
+ aTimeVariable[KVariableIndex4],
+ aTimeVariable[KVariableIndex5],
+ 0
+ ));
+
+ if(error != KErrNone)
+ {
+ aDBBuf.Format(KErrorMessage,error);
+ GBA_TRACE_DEBUG(aDBBuf);
+ return EFalse;
+ }
+
+ *aLifetime = dt;
+
+ GBA_TRACE_END();
+ return ETrue;
+}
+
+
+// ---------------------------------------------------------------------------
+// C3GPPBootstrap::CreateImplementationL()
+// ---------------------------------------------------------------------------
+//
+MUICCInterface* C3GPPBootstrap::RequestUICCInterfaceL()
+ {
+ GBA_TRACE_BEGIN();
+ TAny* ptr = REComSession::CreateImplementationL(iImplementationUID, iDtorIDKey);
+ MUICCInterface* ptyped = static_cast<MUICCInterface*>(ptr);
+ GBA_TRACE_END();
+ return ptyped;
+ }
+
+
+// ---------------------------------------------------------------------------
+// C3GPPBootstrap::IsPluginExistL()
+// ---------------------------------------------------------------------------
+//
+TBool C3GPPBootstrap::IsPluginExistL()
+ {
+ GBA_TRACE_BEGIN();
+ RImplInfoPtrArray array;
+ // Note that a special cleanup function is required to reset and destroy
+ // all items in the array, and then close it.
+ TCleanupItem cleanup(ResetAndDestroyArray, &array);
+ CleanupStack::PushL(cleanup);
+
+ REComSession::ListImplementationsL( KGBAUICCInterfaceUID, array );
+
+ if( array.Count())
+ {
+ CleanupStack::PopAndDestroy(&array); //array, results in a call to ResetAndDestroyArray
+ GBA_TRACE_END();
+ return ETrue;
+ }
+ else
+ {
+ GBA_TRACE_END();
+ CleanupStack::PopAndDestroy(&array); //array, results in a call to ResetAndDestroyArray
+ return EFalse;
+ }
+ }
+
+
+// CleanupEComArray function is used for cleanup support of locally declared arrays
+void ResetAndDestroyArray(TAny* aArray)
+ {
+ GBA_TRACE_BEGIN();
+ (static_cast<RImplInfoPtrArray*> (aArray))->ResetAndDestroy();
+ (static_cast<RImplInfoPtrArray*> (aArray))->Close();
+ GBA_TRACE_END();
+ }
+
+
+// ---------------------------------------------------------------------------
+// C3GPPBootstrap::InterfaceIs2G()
+// ---------------------------------------------------------------------------
+//
+TBool C3GPPBootstrap::InterfaceIs2G()
+ {
+ return iSmartCardInterface->InterfaceIs2G();
+ }
+
+
+// ---------------------------------------------------------------------------
+// C3GPPBootstrap::MakePrivateFilenameL()
+// ---------------------------------------------------------------------------
+//
+void C3GPPBootstrap::MakePrivateFilenameL(RFs& aFs, const TDesC& aLeafName,
+ TDes& aNameOut)
+ {
+ aNameOut.Copy(KGBAStoreStandardDrive);
+ // Get private path
+ TBuf<KStringLength> privatePath;
+ aFs.PrivatePath(privatePath);
+ aNameOut.Append(privatePath);
+ aNameOut.Append(aLeafName);
+ }
+
+
+// ---------------------------------------------------------------------------
+// C3GPPBootstrap::EnsurePathL()
+// ---------------------------------------------------------------------------
+//
+void C3GPPBootstrap::EnsurePathL( RFs& aFs, const TDesC& aFile )
+ {
+ TInt err = aFs.MkDirAll(aFile);
+ if (err != KErrNone && err != KErrAlreadyExists)
+ {
+ User::Leave(err);
+ }
+ }
+
+//EOF
+
+