diff -r f5050f1da672 -r 04becd199f91 javaextensions/satsa/apdu/src.s60/cstspinmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaextensions/satsa/apdu/src.s60/cstspinmanager.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,666 @@ +/* +* Copyright (c) 2008 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: + * +*/ + + +// INCLUDE FILES +#include +#include + +#include "cstsapduexchanger.h" +#include "cstsaccesscontrol.h" +#include "cstspinmanager.h" +#include "cstsauthtype.h" +#include "cstspinattributes.h" +#include "stsapduconstants.h" +#include "cstspinapdu.h" +#include "cstspinapduresp.h" +#include "cstsresphandler.h" +#include "cstspinconverter.h" +#include "logger.h" + + +using namespace java::util; + +namespace java +{ +namespace satsa +{ + +// CONSTANTS +const TInt KSTSMaxPinAttempts = 3; +const TInt KSTSPinHeaderLength = 4; + +CSTSPinManager::CSTSPinManager(CSTSApduExchanger* aApduExchanger, + CSTSAccessControl* aAccessControl, MSTSRespHandler* aRespHandler) : + CActive(EPriorityNormal) +{ + + CActiveScheduler::Add(this); + iApduExchanger = aApduExchanger; + iAccessControl = aAccessControl; + iRespHandler = aRespHandler; + +} + +void CSTSPinManager::ConstructL() +{ + // create pinUI + iSecurityDialog = SecurityDialogFactory::CreateL(); + + iAuthTypeFirstPin = CSTSAuthType::NewL(); + iAuthTypeSecondPin = CSTSAuthType::NewL(); + +} + +CSTSPinManager* CSTSPinManager::NewL(JNIEnv* aJni, jobject aPeer, + CSTSApduExchanger* aApduExchanger, CSTSAccessControl* aAccessControl, + MSTSRespHandler* aRespHandler) +{ + CSTSPinManager + * self = + new(ELeave) CSTSPinManager(aApduExchanger, aAccessControl, aRespHandler); + + self->mJni = aJni; + self->mPeer = aPeer; + CleanupStack::PushL(self); + self->ConstructL(); + + CleanupStack::Pop(self); + return self; +} + +// Destructor +CSTSPinManager::~CSTSPinManager() +{ + Cancel(); + delete iAuthTypeSecondPin; + delete iAuthTypeFirstPin; + if (iSecurityDialog) + { + iSecurityDialog->Release(); // Release deletes the object + } + delete iPinApdu; + delete iPinApduResp; + delete iResponseBuf; + delete mJni; +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::DisablePinL +// Calls proper private methods. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::DisablePinL(TInt aPinID) +{ + PreparePinMethodL(CSTSPinApdu::ESTSDisablePin, aPinID); + ShowPinUI(CSTSPinApdu::ESTSDisablePin); +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::ChangePinL +// Calls proper private methods. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::ChangePinL(TInt aPinID) +{ + + PreparePinMethodL(CSTSPinApdu::ESTSChangePin, aPinID); + ShowPinUI(CSTSPinApdu::ESTSChangePin); + +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::EnablePinL +// Calls proper private methods. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::EnablePinL(TInt aPinID) +{ + + PreparePinMethodL(CSTSPinApdu::ESTSEnablePin, aPinID); + ShowPinUI(CSTSPinApdu::ESTSEnablePin); + +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::EnterPinL +// Calls proper private methods. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::EnterPinL(TInt aPinID) +{ + PreparePinMethodL(CSTSPinApdu::ESTSVerifyPin, aPinID); + ShowPinUI(CSTSPinApdu::ESTSVerifyPin); +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::UnblockPinL +// Calls proper private methods. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::UnblockPinL(TInt aBlockedPinID, TInt aUnblockedPinID) +{ + PreparePinMethodL(CSTSPinApdu::ESTSUnblockPin, aBlockedPinID, + aUnblockedPinID); + ShowPinUI(CSTSPinApdu::ESTSUnblockPin); +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::CancelOperation +// Cancels any pending operation +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::CancelOperation() +{ + LOG(ESATSA, EInfo, "CSTSPinManager::CancelOperation called!"); + Cancel(); +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::RunL +// If PIN value is got from UI, converts user gived PIN values in proper form +// and sends PIN apdu to card. If user has selected cancel option, informs it +// to java side. When apdu sending has returned, checks was user gived value +// correct one and if was not, shows proper PIN ui again. If no retries is left +// shows blocked PIN UI. Supplies response apdus to java side and in error +// conditions supplies proper error code. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::RunL() +{ + LOG1(ESATSA, EInfo, "CSTSPinManager::RunL called!:%d", iStatus.Int()); + + if (iStatus == KErrCancel) + { + LOG(ESATSA, EInfo, "CSTSPinManager::RunL, Cancel selected"); + // if the user selected cancel option. we return null + iRespHandler->OperationComplete(mJni, mPeer, NULL, KSTSErrCancel); + + } + else if (iStatus != KErrNone) + { + LOG(ESATSA, EInfo, "CSTSPinManager::RunL, Error Occurred!!"); + // in other error conditions supply error code + iRespHandler->OperationComplete(mJni, mPeer, NULL, iStatus.Int()); + } + else // no problems + { + switch (iState) + { + case ESendingPINApdu: + { + LOG(ESATSA, EInfo, "CSTSPinManager::RunL, case ESendingPINApdu"); + DoAfterSendApduL(); + break; + } + case EShowingPinBlockedUI: + { + LOG(ESATSA, EInfo, "CSTSPinManager::RunL, case EShowingPinBlockedUI"); + //return PIN method blocked value to java side + //that value is already got from card + DeliverResponseL(); + break; + } + case EShowing1ValuePinUI: + { + LOG(ESATSA, EInfo, "CSTSPinManager::RunL, case EShowing1ValuePinUI"); + DoAfter1ValuePinUIL(); + break; + } + case EShowing2ValuePinUI: + { + LOG(ESATSA, EInfo, "CSTSPinManager::RunL, case EShowing2ValuePinUI"); + DoAfter2ValuePinUIL(); + break; + } + default: + { + break; + } + } + } +} +// ----------------------------------------------------------------------------- +// CSTSPinManager::DoCancel +// Cancels all possible active actions like PIN UIs or apdu exchange +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::DoCancel() +{ + LOG(ESATSA, EInfo, "CSTSPinManager::DoCancel, called"); + iSecurityDialog->Cancel(); + iApduExchanger->CancelExchange(); +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::RunError +// If leave occures in RunL,this method is called. Notifies java side with +// leave code. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CSTSPinManager::RunError(TInt aError) +{ + LOG1(ESATSA, EInfo, "CSTSPinManager::RunError, called: %d", aError); + iRespHandler->OperationComplete(mJni, mPeer, NULL, aError); + // must return KErrNone + return KErrNone; +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::ConvertPINL Converts PIN to correct form for presenting it +// to card. Implementation done according to document "PKCS #15 v1.1: +// Cryptographic Token Information Syntax Standard" chapter "6.8.2.1 +// Transforming a supplied PIN". +// +// EXAMPLE (ascii-) Numeric PIN ‘1234’(10), stored length 8 bytes, and padding +// character ‘FF’(16) gives that the value presented to the card will be +// ‘31323334FFFFFFFF’(16) +// +// Returns: aConvertedPIN: PIN converted to needed format. +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::ConvertPINL(const CSTSPinAttributes& aPinAttributes, + const TDes& aPinValue, HBufC8*& aConvertedPIN) +{ + LOG(ESATSA, EInfo, "CSTSPinManager::ConvertPINL called "); + + TPtr8 convertedPtr(aConvertedPIN->Des()); + + CSTSPinAttributes::TPinType pinType = aPinAttributes.PinType(); + LOG1(ESATSA, EInfo, "CSTSPinManager::ConvertPINL, pintype: %d", pinType); + + if (pinType == CSTSPinAttributes::EUTF8) + { + // if case-sensitive bit is off, convert to uppercase + TBool upperCase = !aPinAttributes.IsPinFlagSet( + CSTSPinAttributes::ECaseSensitive); + CSTSPinConverter::ConvertToUTF8L(aPinValue, convertedPtr, upperCase); + } + else if (pinType == CSTSPinAttributes::EBCD) + { + CSTSPinConverter::ConvertToBCDL(aPinValue, convertedPtr, EFalse); // not half BCD + } + else if (pinType == CSTSPinAttributes::EAsciiNumeric || pinType + == CSTSPinAttributes::EISO9564_1) + { + CSTSPinConverter::ConvertToASCIIL(aPinValue, convertedPtr); + + } + else if (pinType == CSTSPinAttributes::EHalfNibbleBCD) + { + CSTSPinConverter::ConvertToBCDL(aPinValue, convertedPtr, ETrue); // Half BCD + } + else + { + User::Leave(KErrCorrupt); + } + + // If indicated in the pinFlags field, pad to the right with the + // padding character, to stored length + + + // must be popped from cleanupstack before padding + CleanupStack::Pop(aConvertedPIN); + TInt err = CSTSPinConverter::DoBadding(aPinValue, aConvertedPIN, + aPinAttributes.StoredLength(), aPinAttributes.PadChar()[0]); + CleanupStack::PushL(aConvertedPIN); + User::LeaveIfError(err); + +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::PreparePinMethodL Makes preparation common for all PIN +// methods. Checks, is PIN method allowed to use. Gets PIN headers from the +// card and if there was not any, generates it. Sets needed PIN UI parameters. +// Returns: +// iPinApdu: Saves APDU into this member variable +// iPinApduResp: Saves response APDU into this member variable +// iAuthTypeFirstPin: Saves PIN attributes into this member variable +// iAuthTypeSecondPin: Saves PIN attributes into this member variable +// iPINParamsFirstPin: Saves PIN UI parameters into this member variable +// iPINParamsSecondPin: Saves PIN UI parameters into this member variable +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::PreparePinMethodL( + CSTSPinApdu::TSTSPinApduType aPinApduType, TInt aFirstPinID, + TInt aUnblockedPinID) +{ + LOG(ESATSA, EInfo, "CSTSPinManager::PreparePinMethodL called"); + + iPinApduType = aPinApduType; + + // is pinmethods supported to use with card application + if (!iAccessControl->IsAllowedPinMethod()) + { + ELOG(ESATSA, "CSTSPinManager::PreparePinMethodL, Not supported"); + User::Leave(KSTSErrSecurity + KSTSErrSECNoRightsPin); + } + + // gets the pin apdu header part from the card, if there is any + TPtrC8 headerPtr(iAccessControl->GetPinHeaderL(aFirstPinID, + (TPinApduType) aPinApduType)); + + iAuthTypeFirstPin->CopyL(iAccessControl->GetPinAttributesL(aFirstPinID)); + + // leaves if PIN flags does not allow this PIN apdu + iAccessControl->CheckPinFlagsL((TPinApduType) aPinApduType); + + // if pin headers are not found, + if (headerPtr == KNullDesC8()) + { + // Pin reference is used if the APDU headers are not specified in the ACL + CSTSPinApdu* pinApdu = CSTSPinApdu::NewL(aPinApduType, + iAuthTypeFirstPin->PinAttributes().PinReference(), + CSTSApdu::ESTSUICC); + delete iPinApdu; + iPinApdu = pinApdu; + } + else + { + LOG(ESATSA, EInfo, "CSTSPinManager::PreparePinMethodL, specified header used"); + CSTSCmdApdu* tmp = CSTSCmdApdu::NewL(headerPtr, CSTSApdu::ESTSUICC); + delete iPinApdu; + iPinApdu = tmp; + } + + // check is the J2ME application allowed to use this apdu + if (!iAccessControl->IsAllowedApduL(iPinApdu->Header())) + { + ELOG(ESATSA, "CSTSPinManager::PreparePinMethodL, Not allowed"); + // if not allowed + User::Leave(KSTSErrSecurity + KSTSErrSECIllegalApdu); + } + + SetPINUIParametersL(iAuthTypeFirstPin, iPINParamsFirstPin); + + // In unblockPIN case we need to initialize parameters of unblocked PIN + if (aPinApduType == EUnblockPinAPDU) + { + LOG(ESATSA, EInfo, "unblock parameters"); + iAuthTypeSecondPin->CopyL(iAccessControl->GetPinAttributesL( + aUnblockedPinID)); + SetPINUIParametersL(iAuthTypeSecondPin, iPINParamsSecondPin); + } + + iRetries = EFirstTime; + LOG(ESATSA, EInfo, "-- CSTSPinManager::PreparePinMethodL"); +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::ShowPinUI Shows PIN UI for getting PIN value or values. +// Shows correct UI depending on which PIN method is used. +// +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::ShowPinUI(CSTSPinApdu::TSTSPinApduType aPinApduType) +{ + LOG(ESATSA, EInfo, "CSTSPinManager::ShowPinUI+"); + TBool retrying = iRetries == ERetrying; + TPinManagerState state = EShowing1ValuePinUI; + // get PIN from the user with UI + if (aPinApduType == EVerifyPinAPDU) + { + iSecurityDialog->EnterPIN(iPINParamsFirstPin, retrying, + iPinValueForFirstPin, iStatus); + } + else if (aPinApduType == EEnablePinAPDU) + { + iSecurityDialog->EnablePIN(iPINParamsFirstPin, retrying, + iPinValueForFirstPin, iStatus); + + } + else if (aPinApduType == EDisablePinAPDU) + { + iSecurityDialog->DisablePIN(iPINParamsFirstPin, retrying, + iPinValueForFirstPin, iStatus); + } + else if (aPinApduType == EChangePinAPDU) + { + state = EShowing2ValuePinUI; + iSecurityDialog->ChangePIN(iPINParamsFirstPin, retrying, + iPinValueForFirstPin, iPinValueForSecondPin, iStatus); + } + else if (aPinApduType == EUnblockPinAPDU) + { + state = EShowing2ValuePinUI; + iSecurityDialog->UnblockPIN(iPINParamsFirstPin, iPINParamsSecondPin, + retrying, iPinValueForFirstPin, iPinValueForSecondPin, iStatus); + } + else + { + + } + + SetActive(); + iState = state; + +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::DeliverResponseL +// Saves responsebytes to member variable and delivers them to java side with +// help of response handler. +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::DeliverResponseL() +{ + LOG(ESATSA, EInfo, "CSTSPinManager::DeliverResponseL, called"); + HBufC8* tmp = iPinApduResp->ResponseBytes().AllocL(); + delete iResponseBuf; + iResponseBuf = tmp; + + iRespHandler->OperationComplete(mJni, mPeer, iResponseBuf, KErrNone); + +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::SetPINUIParametersL +// Uses authtype parameter to get needed values and sets them to gived PINParams +// variable. +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::SetPINUIParametersL(const CSTSAuthType* aAuthType, + TPINParams& aPINParams) +{ + // maximum length is optional in card, so we need to set something for + // PIN UI needs + TInt maxLength = PINMaxLength(aAuthType); + TInt minLength = aAuthType->PinAttributes().MinLength(); + + // create TPINParams + + // label that identifies the PIN + aPINParams.iPINLabel = aAuthType->Label(); + aPINParams.iTokenLabel = iAccessControl->TokenLabelL(); + aPINParams.iMinLength = minLength; + aPINParams.iMaxLength = maxLength; + +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::DoAfterSendApduL +// Checks response adpu and depending on response delivers response bytes +// to response handler, shows PIN Blocked UI or shows previous PIN UI again. +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::DoAfterSendApduL() +{ + //check response apdu, and show UI again if wrong pin value + CSTSPinApduResp* resp = CSTSPinApduResp::NewL(); + delete iPinApduResp; + iPinApduResp = resp; + iApduExchanger->GetResponseBytes(*iPinApduResp); + + TInt retriesLeft = iPinApduResp->RetriesLeft(); + + //if response not indicate retresleft value + if (retriesLeft == KErrNotFound) + { + // return response bytes to java side + DeliverResponseL(); + } + + //if pin is blocked, call iSecurityDialog::PINBlocked method + else if (iPinApduResp->IsBlocked()) + { + // save state to member variable that we can return asynchronous + // after SetActive call + iRetries = EPINBlocked; + + iSecurityDialog->PINBlocked(iPINParamsFirstPin, iStatus); + iState = EShowingPinBlockedUI; + SetActive(); + } + // if user gived pin value was incorrect + else if (retriesLeft < KSTSMaxPinAttempts && retriesLeft > 0) + { + iRetries = ERetrying; + // "initialize" header + iPinApdu->ApduBytes().SetLength(KSTSPinHeaderLength); + // show UI again, because PIN value was wrong + ShowPinUI(iPinApduType); + } + // if max pin attemps is left, user gived pin value was correct + // one and we can supply response bytes to java side + else if (retriesLeft == KSTSMaxPinAttempts) + { + // return response bytes to java side + DeliverResponseL(); + } + else + { + User::Leave(KSTSErrIO + KSTSErrIOCommProblems); + } +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::DoAfter1ValuePinUIL +// Convers PIN value gor from UI to proper form and sends proper PIN apdu to +// smart card. +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::DoAfter1ValuePinUIL() +{ + HBufC8* convertedBuf = + HBufC8::NewLC(PINMaxLength(iAuthTypeFirstPin, ETrue)); + + ConvertPINL(iAuthTypeFirstPin->PinAttributes(), iPinValueForFirstPin, + convertedBuf); + TPtr8 convertedPin(convertedBuf->Des()); + + iPinApdu->AppendDatabytesL(convertedPin); + + CleanupStack::PopAndDestroy(convertedBuf); + + iApduExchanger->ExchangeApduAsync(iStatus, *iPinApdu); + iState = ESendingPINApdu; + SetActive(); + +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::DoAfter2ValuePinUIL +// Convers PIN values gor from UI to proper form and sends proper PIN apdu to +// smart card. +// ----------------------------------------------------------------------------- +// +void CSTSPinManager::DoAfter2ValuePinUIL() +{ + + // in changePIN case we use same pin parameters for both pins + if (iPinApduType == EChangePinAPDU) + { + iAuthTypeSecondPin->CopyL(*iAuthTypeFirstPin); + } + + // finds maximum length to create large enough buffer + TInt pinValue2MaxLength = PINMaxLength(iAuthTypeSecondPin, ETrue); + + HBufC8* convertedBuf1 = HBufC8::NewLC((PINMaxLength(iAuthTypeFirstPin, + ETrue)) +pinValue2MaxLength); + + ConvertPINL(iAuthTypeFirstPin->PinAttributes(), iPinValueForFirstPin, + convertedBuf1); + + HBufC8* convertedBuf2 = HBufC8::NewLC(pinValue2MaxLength); + ConvertPINL(iAuthTypeSecondPin->PinAttributes(), iPinValueForSecondPin, + convertedBuf2); + + TPtr8 convertedPins(convertedBuf1->Des()); + convertedPins.Append(convertedBuf2->Des()); + + iPinApdu->AppendDatabytesL(convertedPins); + + CleanupStack::PopAndDestroy(convertedBuf2); + CleanupStack::PopAndDestroy(convertedBuf1); + + iApduExchanger->ExchangeApduAsync(iStatus, *iPinApdu); + iState = ESendingPINApdu; + SetActive(); + +} + +// ----------------------------------------------------------------------------- +// CSTSPinManager::PINMaxLength +// Is used to find PIN value max length for UI and for buffer creation. For UI +// needs aReturnBiggest parameter is not used and method will return proper +// maxLength of PIN. If is used for creating buffer for converted PIN +// aReturnBiggest parameter must be set to ETrue. Then method will return either +// maxlength or stored length value depending on which one is bigger. +// ----------------------------------------------------------------------------- +// +TInt CSTSPinManager::PINMaxLength(const CSTSAuthType* aAuthType, + TBool aReturnBiggest) const +{ + TInt returnValue; + TInt maxLength = aAuthType->PinAttributes().MaxLength(); + TInt storedLength = aAuthType->PinAttributes().StoredLength(); + + // maximum length is optional in card, so we need to set something for + // PIN UI needs + if (maxLength == KErrNotFound) + { + // if optional maxLength is not found, we use mandatory stored length + maxLength = storedLength; + } + returnValue = maxLength; + + // compares maxlength and stored length + if (aReturnBiggest) + { + if (storedLength > maxLength) + { + returnValue = storedLength; + } + } + + return returnValue; +} + +} // namespace satsa +} // namespace java +// End of File +