diff -r 000000000000 -r 164170e6151a gba/gbaserver/src/bootstrap.cpp --- /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 //for base64 en/decoding +#include +#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,""); +_LIT8(KBTIDEndFlag,""); +_LIT8(KLifetimeFlag,""); +_LIT8(KLifetimeEndFlag,""); +_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 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 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 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(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 (aArray))->ResetAndDestroy(); + (static_cast (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 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 + +