telephonyserver/etelmultimode/CETEL/mm_scappeap.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyserver/etelmultimode/CETEL/mm_scappeap.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,613 @@
+// Copyright (c) 2006-2009 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:
+// This file contains the definition for the ETelMM sub-session
+// RMobileSmartCardEap, which allows access to EAP supporting UICC
+// applications and all their functionality.
+// (See specification: ETSI TS 102 310 v6.2.0)
+// 
+//
+
+/**
+ @file
+*/
+
+// From core API
+#include <etelext.h>
+
+// Multimode header files
+#include <etelmm.h>
+#include "mm_hold.h"
+#include "mmretrieve.h"
+
+//
+//
+//  RMobileSmartCardEap
+//
+//
+
+/**
+Default empty constructor, and is present only to support virtual
+function table export.
+
+@publishedPartner
+@released
+*/
+EXPORT_C RMobileSmartCardEap::RMobileSmartCardEap()
+	: iMmPtrHolder(NULL), iOwnsEapMethodLock(EFalse)
+	{
+	}
+
+/**
+This function opens a RMobileSmartCardEap sub-session from RMobilePhone
+that will refer to the application referenced by aAID.  It will be
+assumed that the application exists and contains a DF_EAP for the
+aEapType specified.  The client must call
+RMobileSmartCardEap::InitialiseEapMethod() to ensure correct
+functionality of this sub-session.
+
+@param aPhone The RMobilePhone sub-session relative to which this
+              sub-session will open.
+@param aAId The UICC Application ID, which should be of one that has
+            EAP support.
+@param aEapType The EAP method type that this sub-session will use
+                under the aAID application.
+
+@return KErrNone if successful, otherwise a system-wide error code.
+@see RMobileSmartCardEap::InitialiseEapMethod()
+
+@capability None
+
+@publishedPartner
+@released
+*/
+EXPORT_C TInt RMobileSmartCardEap::Open(RMobilePhone& aPhone, const RMobilePhone::TAID& aAID, const TEapType& aEapType)
+	{
+	RSessionBase* session = &aPhone.SessionHandle();
+	__ASSERT_ALWAYS(session != NULL, PanicClient(EEtelPanicNullHandle));
+	TInt subSessionHandle = aPhone.SubSessionHandle();
+	__ASSERT_ALWAYS(subSessionHandle != NULL, PanicClient(EEtelPanicNullHandle));
+
+	TRAPD(ret, ConstructL());
+	if (ret != KErrNone)
+		{
+		Destruct();
+		return ret;
+		}
+
+	// Appending the application ID and Eap Type to the name of the
+	// subsession; plus two one-byte delimeters indicating lengths.
+	// See var appIdbuf for why KAIDSize is multiplied by 2.
+	TBufC<SCEAP_SSN_LENGTH + RMobilePhone::KAIDSize*2 +
+	      KEapTypeSize + 2> nameBuf(KETelSmartCardEapSession); // 2 for delimeters
+	TPtr name(nameBuf.Des());
+
+	// the length of the AID as a Sept ASCII character
+	TChar lengthAIDChar = SeptChar(aAID.Length());
+
+	// the value of the AID
+	// converted to a 16-bit string representation.  Multiply by 2,
+	// since each AID byte is represented as two sem-octects.
+	TBufC<2*RMobilePhone::KAIDSize> appIdbuf;
+	TPtr appIdPtr(appIdbuf.Des());
+	ConvertBinToText(aAID, appIdPtr);
+
+	// the length of the EapType
+	TInt lengthEapType = aEapType.Length();
+	TChar charEapType = SeptChar(lengthEapType);
+
+	// the value of the EapType (converted to 16-bit)
+	TBufC<KEapTypeSize> eapTypeBuf;
+	TPtr eapTypePtr(eapTypeBuf.Des());
+	eapTypePtr.Copy(aEapType);
+
+	// appending...
+	name.Append(lengthAIDChar);
+	name.Append(appIdPtr);
+	name.Append(charEapType);
+	name.Append(eapTypePtr);
+
+	TIpcArgs args(&name, TIpcArgs::ENothing, subSessionHandle);
+	SetSessionHandle(*session);
+	ret = CreateSubSession(*session, EEtelOpenFromSubSession, args);
+
+	if (ret != KErrNone)
+		{
+		Destruct();
+		}
+
+	return ret;
+	}
+
+/**
+This function member closes a RMobileSmartCardEap sub-session.  The
+Close() request also attempts to release this instance's lock on the
+<AID,EAPType> (DF_EAP).
+
+@panic Panics the client with ETel Panic EEtelPanicHandleNotClosed, if
+       this instance owns the lock on the DF_EAP but could not release
+       some resource to allow other instances to gain access.
+       (However, it should be noted that the TSY can take control of
+       DF_EAP access in the event that a client dies in such a manner.)
+@see RMobileSmartCardEap::ReleaseEapMethod()
+
+@capability None
+
+@publishedPartner
+@released
+*/
+EXPORT_C void RMobileSmartCardEap::Close()
+	{
+	if (iOwnsEapMethodLock)
+		{
+		TInt err = ReleaseEapMethod();
+		if (err != KErrNone)
+			{
+			PanicClient(EEtelPanicHandleNotClosed);
+			}
+		}
+
+	CloseSubSession(EEtelClose);
+	Destruct();
+	}
+
+/**
+Initialises access to the DF_EAP.  This will ensure the aAID and
+aEapType given in the RMobileSmartCardEap::Open() exist and are
+accessible.  If for any reason the sub-session is inaccessible, the
+client can request a notification for state changes using
+RMobileSmartCardEap::NotifyEapMethodAccessStatusChange().
+
+@param aReqStatus Returns the result code after the asynchronous call
+                  completes.  Successful completion is only achieved
+                  when the client is the first to request
+                  initialisation on this sub-session.
+                  KErrInUse will be returned if another
+                  RMobileSmartCardEap instance successfully achieved
+                  initialisation first.
+                  Any other error code returned as request completion,
+                  suggests another problem in the system and the client
+                  must call RMobileSmartCardEap::Close() or
+                  RMobileSmartCardEap::ReleaseEapMethod() at some
+                  point, to allow other clients to use this same
+                  <AID,EapType> sub-session.
+@see RMobileSmartCardEap::Open()
+@see RMobileSmartCardEap::NotifyEapMethodAccessStatusChange()
+
+@capability ReadDeviceData
+@capability NetworkControl
+
+@publishedPartner
+@released
+*/
+EXPORT_C void RMobileSmartCardEap::InitialiseEapMethod(TRequestStatus& aReqStatus)
+	{
+	__ASSERT_ALWAYS(iMmPtrHolder != NULL, PanicClient(EEtelPanicNullHandle));
+
+	if (!iOwnsEapMethodLock)
+		{
+		TInt ret = KErrNone;
+
+		TInt semHandle = SendReceive(EEtelGlobalKernelObjectHandle);
+
+		if(semHandle > 0)
+			{
+			ret = iSemaphore.SetReturnedHandle(semHandle); // although this will take an error as handle, best to specify our own explicit KErrBadHandle in the following else.
+			}
+		else
+			{
+			ret = KErrBadHandle;
+			}
+
+		if (ret != KErrNone)
+			{
+			TRequestStatus* status1 = &aReqStatus;
+			User::RequestComplete(status1, ret);
+			return;
+			}
+
+		ret = iSemaphore.Wait(10);
+		if (ret == KErrTimedOut)
+			{
+			TRequestStatus* status2 = &aReqStatus;
+			User::RequestComplete(status2, KErrInUse);
+			return;
+			}
+		else if (ret != KErrNone)
+			{
+			TRequestStatus* status3 = &aReqStatus;
+			User::RequestComplete(status3, ret);
+			return;
+			}
+
+		iOwnsEapMethodLock = ETrue;
+		}
+
+	RThread ownerThread;
+	TThreadId ownerThreadId = ownerThread.Id();
+
+	iMmPtrHolder->iOwnerThreadId = ownerThreadId;
+	TPtrC8& ptr1 = iMmPtrHolder->SetC(CMobileSmartCardEapPtrHolder::ESlot1InitialiseEapMethod, iMmPtrHolder->iOwnerThreadId);
+
+	Set(EMobileSmartCardEapInitialiseEapMethod, aReqStatus, ptr1);
+	}
+
+/**
+Delayed construction of heap stored data members.
+
+@leave KErrNoMemory Heap memory allocation failure for
+                    CMobileSmartCardEapPtrHolder object.
+
+@publishedPartner
+@released
+*/
+EXPORT_C void RMobileSmartCardEap::ConstructL()
+	{
+	__ASSERT_ALWAYS(iMmPtrHolder == NULL, PanicClient(EEtelPanicHandleNotClosed));
+	iMmPtrHolder = CMobileSmartCardEapPtrHolder::NewL(CMobileSmartCardEapPtrHolder::EMaxNumberSmartCardEapPtrSlots,
+	                                                  CMobileSmartCardEapPtrHolder::EMaxNumberSmartCardEapPtrCSlots);
+	}
+
+/**
+Called internally when RMobileSmartCardEap instance is no longer
+required, to ensure clean up of data members from memory.
+
+@publishedPartner
+@released
+*/
+EXPORT_C void RMobileSmartCardEap::Destruct()
+	{
+	delete iMmPtrHolder;
+	iMmPtrHolder = NULL;
+	ResetSessionHandle();
+	}
+
+/**
+Default constructor, initialising version number of this data
+structure.
+
+@see TMultimodeEtelV6Api
+
+@publishedPartner
+@released
+*/
+EXPORT_C RMobileSmartCardEap::TEapUserIdentityV6::TEapUserIdentityV6()
+	{
+	iExtensionId = KEtelExtMultimodeV6;
+	}
+
+/**
+Default constructor, initialising version number of this data
+structure.
+
+@see TMultimodeEtelV6Api
+
+@publishedPartner
+@released
+*/
+EXPORT_C RMobileSmartCardEap::TEapKeyV6::TEapKeyV6()
+	{
+	iExtensionId = KEtelExtMultimodeV6;
+	}
+
+/**
+This method allows the client to retrieve the user identity data to be
+used for an EAP based authentication.  The client will specify which
+identity type they want to read by setting the aRequestIdType parameter
+to the appropriate enumeration value.  The user Id data is returned as
+a packaged instance of TEapUserIdentityV6 within the aUserId.
+
+An example base band functionality that would be used to service this
+request is the +CEPR (see section 8.48 of 3GPP TS 27.007 v6.8.0) AT-
+command, which returns "identity" and "pseudonym" as two of its defined
+values.
+
+EF_PUId and EF_Ps hold these identities (specified in sections 7.3 and
+7.4, respectively, of ETSI TS 102.310 v6.2.0).
+
+@param aReqStatus Returns the result code after the asynchronous call
+                  completes.
+@param aRequestIdType Used to request the specific identity the client
+                      wishes to retrieve.
+@param aUserId On completion, will be populated with the user identity
+               requested by the client.
+
+@capability ReadDeviceData
+
+@publishedPartner
+@released
+*/
+EXPORT_C void RMobileSmartCardEap::GetUserIdentity(TRequestStatus& aReqStatus, const TEapUserIdType aRequestedIdType, TDes8& aUserId)
+	{
+	__ASSERT_ALWAYS(iMmPtrHolder != NULL, PanicClient(EEtelPanicNullHandle));
+
+	if (iSemaphore.Handle() == 0)
+		{
+		TRequestStatus* status1 = &aReqStatus;
+		User::RequestComplete(status1, KErrBadHandle);
+		return;
+		}
+
+	if (!iOwnsEapMethodLock)
+		{
+		TRequestStatus* status2 = &aReqStatus;
+		User::RequestComplete(status2, KErrInUse);
+		return;
+		}
+
+	iMmPtrHolder->iEapUserIdType = aRequestedIdType;
+	TPtrC8& ptr1 = iMmPtrHolder->SetC(CMobileSmartCardEapPtrHolder::ESlot1GetUserId, iMmPtrHolder->iEapUserIdType);
+
+	SetAndGet(EMobileSmartCardEapGetUserIdentity, aReqStatus, ptr1, aUserId);
+	}
+
+/**
+The authentication status is obtained from the EAP supporting UICC
+application's EF_EAPSTATUS.  It specifies the current state of
+authentication in the DF_EAP.
+
+@param aReqStatus Returns the result code after the asynchronous call
+                  completes.
+@param aAuthStatus On request completion, will store the current
+                   authentication status of the DF_EAP.
+
+@capability ReadDeviceData
+
+@publishedPartner
+@released
+*/
+EXPORT_C void RMobileSmartCardEap::GetAuthenticationStatus(TRequestStatus& aReqStatus, TEapAuthStatus& aAuthStatus)
+	{
+	__ASSERT_ALWAYS(iMmPtrHolder != NULL, PanicClient(EEtelPanicNullHandle));
+
+	if (iSemaphore.Handle() == 0)
+		{
+		TRequestStatus* status1 = &aReqStatus;
+		User::RequestComplete(status1, KErrBadHandle);
+		return;
+		}
+
+	if (!iOwnsEapMethodLock)
+		{
+		TRequestStatus* status2 = &aReqStatus;
+		User::RequestComplete(status2, KErrInUse);
+		return;
+		}
+
+	TPtr8& ptr1 = iMmPtrHolder->Set(CMobileSmartCardEapPtrHolder::ESlot1GetAuthStatus, aAuthStatus);
+
+	Get(EMobileSmartCardEapGetAuthenticationStatus, aReqStatus, ptr1);
+	}
+
+/**
+Retrieves the generated key stored in EF_EAPKEYS of the DF_EAP (see
+section 7.1 of ETSI TS 102.310 v6.2.0).
+
+@param aReqStatus Returns the result code after the asynchronous call
+                  completes.
+@param aRequestedKey Used to specify which of the keys the client is
+                     requesting.
+@param aKey Populated with the requested key on request completion.
+
+@capability ReadDeviceData
+
+@publishedPartner
+@released
+*/
+EXPORT_C void RMobileSmartCardEap::GetEapKey(TRequestStatus& aReqStatus, const TEapKeyTag aRequestedKey, TDes8& aKey)
+	{
+	__ASSERT_ALWAYS(iMmPtrHolder != NULL, PanicClient(EEtelPanicNullHandle));
+
+	if (iSemaphore.Handle() == 0)
+		{
+		TRequestStatus* status1 = &aReqStatus;
+		User::RequestComplete(status1, KErrBadHandle);
+		return;
+		}
+
+	if (!iOwnsEapMethodLock)
+		{
+		TRequestStatus* status2 = &aReqStatus;
+		User::RequestComplete(status2, KErrInUse);
+		return;
+		}
+
+	iMmPtrHolder->iReqEapKeyTag = aRequestedKey;
+	TPtrC8& ptr1 = iMmPtrHolder->SetC(CMobileSmartCardEapPtrHolder::ESlot1GetEapKey, iMmPtrHolder->iReqEapKeyTag);
+
+	SetAndGet(EMobileSmartCardEapGetEapKey, aReqStatus, ptr1, aKey);
+	}
+
+/**
+Relinquishes ownership of the DF_EAP, to allow other clients to use it.
+Although the request completes relatively quickly, it will set the
+server's process running to attempt a deactivate on the sub-session's
+corresponding application.  The deactivate will allow future clients to
+initialise the application, which should reset all its DF_EAP states.
+
+The initial state change of the sub-session will be
+EEapMethodUnableToInitialise, as the request completes without waiting
+for the application's deactivation.  After the sub-session is able to
+deactivate the app, the state will change to EEapMethodAvailable.
+
+The server will make a decision on deactivating the application based
+on whether there are other sub-session open to the same application
+(but different EAP types/ DF_EAP).  Only when the application is no
+longer in use, that the server will deactivate it.
+
+Notifications can be posted using
+RMobileSmartCardEap::NotifyEapMethodAccessStatusChange() to observe
+such state changes.
+
+@return If an error is returned, this object will maintain lock on the
+        UICC application's DF_EAP.
+@see RMobileSmartCardEap::NotifyEapMethodAccessStatusChange()
+
+@capability ReadDeviceData
+
+@publishedPartner
+@released
+*/
+EXPORT_C TInt RMobileSmartCardEap::ReleaseEapMethod()
+	{
+	if (iSemaphore.Handle() == 0)
+		{
+		return KErrBadHandle;
+		}
+
+	if (!iOwnsEapMethodLock)
+		{
+		return KErrInUse;
+		}
+
+	TInt ret = Blank(EMobileSmartCardEapReleaseEapMethod);
+
+	if (ret == KErrNone)
+		{
+		iSemaphore.Signal();
+		iOwnsEapMethodLock = EFalse;
+		}
+
+	return ret;
+	}
+
+/**
+Synchronous request to get the current status of the DF_EAP.  This
+state value is held by the platform to ensure exclusive access to a
+DF_EAP; it is NOT a state of any Smart Card Application file.
+
+@param aEapMethodStatus Returns the sub-session's current value of
+                        RMobileSmartCardEap::TEapMethodAccessStatus.
+
+@capability ReadDeviceData
+
+@publishedPartner
+@released
+*/
+EXPORT_C TInt RMobileSmartCardEap::GetEapMethodAccessStatus(TEapMethodAccessStatus& aEapMethodStatus)
+	{
+	TPckg<TEapMethodAccessStatus> ptr1(aEapMethodStatus);
+	return Get(EMobileSmartCardEapGetEapMethodAccessStatus, ptr1);
+	}
+
+/**
+Notifies the client when the EAP method's (DF_EAP's) access status
+changes.
+
+The status begins as EEapMethodAvailable when the DF_EAP is first used;
+before RMobileSmartCardEap::InitialiseEapMethod() is called by the
+client.  EEapMethodInUseApplicationActive state is given after the
+first client initialises... various cases cause transformations to
+states EEapMethodUnableToInitialise or
+EEapMethodInUseApplicationInactive.
+
+@param aReqStatus Returns the result code after the asynchronous call
+                  completes.
+@param aEapMethodStatus Returns the 
+                        RMobileSmartCardEap::TEapMethodAccessStatus
+                        value when the status changes on this sub-
+                        session.
+@see RMobileSmartCardEap::InitialiseEapMethod()
+@see RMobileSmartCardEap::GetEapMethodAccessStatus()
+@see RMobileSmartCardEap::ReleaseEapMethod()
+
+@capability ReadDeviceData
+
+@publishedPartner
+@released
+*/
+EXPORT_C void RMobileSmartCardEap::NotifyEapMethodAccessStatusChange(TRequestStatus& aReqStatus, TEapMethodAccessStatus& aEapMethodStatus)
+	{
+	__ASSERT_ALWAYS(iMmPtrHolder != NULL, PanicClient(EEtelPanicNullHandle));
+
+	TPtr8& ptr1 = iMmPtrHolder->Set(CMobileSmartCardEapPtrHolder::ESlot1NotifyEapMethodAccess, aEapMethodStatus);
+
+	Get(EMobileSmartCardEapNotifyEapMethodAccessStatusChange, aReqStatus, ptr1);
+	}
+
+/**
+Returns whether this RMobileSmartCardEap instance has ownership of its
+corresponding DF_EAP.
+
+@return ETrue only if this instance of RMobileSmartCardEap was the
+        first to call RMobileSmartCardEap::InitialiseEapMethod()
+        successfully.
+@see RMobileSmartCardEap::InitialiseEapMethod()
+@see RMobileSmartCardEap::Open()
+
+@capability None
+
+@publishedPartner
+@released
+*/
+EXPORT_C TBool RMobileSmartCardEap::IsEapMethodOwner() const
+	{
+	return iOwnsEapMethodLock;
+	}
+
+
+// helpers //
+
+/**
+Returns the character that corresponds to the value of its parameter
+(base 17!).
+
+@param aDigit an integer between 0 and 16.
+@return A TChar representing one of '0' to '9' or 'A' to 'G'.
+
+@internalComponent
+@released
+*/
+TChar RMobileSmartCardEap::SeptChar(TInt aDigit)
+	{
+	TChar ret(0);
+	if ((aDigit < 0) || (aDigit > 16))
+		{
+		PanicClient(EEtelPanicHandleNotOpen);
+		}
+	else
+		{
+		if (aDigit < 10)
+			{
+			ret = aDigit + (TUint)'0';
+			}
+		else
+			{
+			ret = aDigit - 10 + (TUint)'A';
+			}
+		}
+	return ret;
+	}
+
+/**
+This function is used by RMobileSmartCardEap::Open() to convert the
+TAID (which is binary data) to a string that can be passed through
+ETel.  The conversion changes the binary data to a string of
+hexadecimal semi-octets.
+
+@param aBinData Buffer containing the binary data to be converted.
+@param aText Buffer will contain the text representation of aBinData on
+             return.
+
+@see RMobileSmartCardEap::Open()
+*/
+void RMobileSmartCardEap::ConvertBinToText(const TDesC8& aBinData, TDes& aText)
+	{
+	TInt binLength = aBinData.Length();
+
+	for (TInt pos = 0; pos < binLength; pos++)
+		{
+		_LIT(format, "%02X");
+		aText.AppendFormat(format, aBinData[pos]);
+		}
+	}