gba/gbaserver/src/bootstrap.cpp
changeset 0 164170e6151a
child 8 ece4bbb094df
--- /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
+
+