wvsettings20/IMPSSrc/CIMPSSAPSecurer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:41:52 +0200
changeset 0 094583676ce7
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2005 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:  IMPS SAP Settings Store implementation.
*
*/


//  INCLUDES
#include 	"CIMPSSAPSecurer.h"
#include	"IMPSSAPSettingsStoreDefinitions.h"

#include    <3des.h> 		//3des encryption/decryption
#include	<etelmm.h> 		// for getting the IMEI
#include	<mmtsy_names.h>
#include 	<symmetric.h>

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CIMPSSAPSecurer::CIMPSSAPSecurer
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CIMPSSAPSecurer::CIMPSSAPSecurer()
    {
    }

// -----------------------------------------------------------------------------
// CIMPSSAPSecurer::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CIMPSSAPSecurer::ConstructL()
    {
    // Get the encryption key
    iEncryptionKey = HBufC8::NewL( KSSS3DESKeySize );
    TPtr8 keyPtr( iEncryptionKey->Des() );
    GetPwdKeyL( keyPtr );

    // Create encryptor and decryptor
    iEncryptor = C3DESEncryptor::NewL( keyPtr );
    iDecryptor = C3DESDecryptor::NewL( keyPtr );

    iTransformBlock = HBufC8::NewMaxL( iEncryptor->BlockSize() );
    }

// -----------------------------------------------------------------------------
// CIMPSSAPSecurer::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CIMPSSAPSecurer* CIMPSSAPSecurer::NewL()
    {
    CIMPSSAPSecurer* self = new( ELeave ) CIMPSSAPSecurer();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }


// Destructor
CIMPSSAPSecurer::~CIMPSSAPSecurer()
    {
    delete iTransformBlock;
    delete iEncryptionKey;
    delete iEncryptor;
    delete iDecryptor;
    }

// -----------------------------------------------------------------------------
// CIMPSSAPSecurer::EncryptPwdL()
// Encrypts password
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
HBufC* CIMPSSAPSecurer::EncryptPwdL( const TDesC& aPwdBuffer )
    {
    HBufC* encrypted;
    // first check for 0 length buffers
    if ( aPwdBuffer.Length() == 0 )
        {
        encrypted = HBufC::NewMaxL( 0 );
        return encrypted;
        }

    // character for padding
    TChar KPad( 0x00 );

    TUint8* tempPtr = ( TUint8* ) aPwdBuffer.Ptr();
    TPtr8 buf( tempPtr, aPwdBuffer.Size(), aPwdBuffer.Size() );
    TInt bufSize = aPwdBuffer.Size();

    const TInt blocksize = iEncryptor->BlockSize();
    const TInt remainder = bufSize % blocksize;

    // make the result buffer big enough for the padding ==>
    // round upwards to next multiple of blocksize
    if ( remainder == 0 )
        {
        encrypted = HBufC::NewMaxLC( bufSize / 2 );
        }
    else
        {
        encrypted = HBufC::NewMaxLC( ( bufSize + ( blocksize - remainder )  ) / 2 );
        }

    TUint8* tempEncPtr = ( TUint8* ) encrypted->Ptr();
    TPtr8 encPtr( tempEncPtr, NULL, encrypted->Des().MaxSize() );
    TPtr8 transformPtr( iTransformBlock->Des() );

    TInt offset( 0 );
    while ( offset <= bufSize - blocksize )
        {
        transformPtr = buf.Mid( offset, blocksize );
        iEncryptor->Transform( transformPtr );
        encPtr.Append( transformPtr );
        offset += blocksize;
        }

    // Handle last block. If last block is not 8 characters long add padding
    // nulls to end of it.
    if ( remainder != 0 )
        {
        transformPtr = buf.Mid( offset );
        transformPtr.AppendFill( KPad, blocksize - remainder );
        iEncryptor->Transform( transformPtr );
        encPtr.Append( transformPtr );
        }

    CleanupStack::Pop( encrypted );
    return encrypted;
    }

// -----------------------------------------------------------------------------
// CIMPSSAPSecurer::DecryptPwdL()
// Decrypts password
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
HBufC* CIMPSSAPSecurer::DecryptPwdL( const TDesC& aPwdBuffer )
    {
    HBufC* decrypted;
    // first check for 0 length buffers
    if ( aPwdBuffer.Length() == 0 )
        {
        decrypted = HBufC::NewMaxL( 0 );
        return decrypted;
        }
    // character for padding
    TChar KPad( 0x00 );

    TUint8* tempPtr = ( TUint8* ) aPwdBuffer.Ptr();
    TPtr8 buf( tempPtr, aPwdBuffer.Size(), aPwdBuffer.Size() );
    TInt bufSize = aPwdBuffer.Size();

    const TInt blocksize = iEncryptor->BlockSize();
    const TInt remainder = bufSize % blocksize;

    // make the result buffer big enough for the padding ==>
    // round upwards to next multiple of blocksize
    if ( remainder == 0 )
        {
        decrypted = HBufC::NewMaxLC( bufSize / 2 );
        }
    else
        {
        decrypted = HBufC::NewMaxLC( ( bufSize + ( blocksize - remainder ) ) / 2 );
        }

    TUint8* tempDecPtr = ( TUint8* ) decrypted->Ptr();
    TPtr8 decPtr( tempDecPtr, NULL, decrypted->Des().MaxSize() );
    TPtr8 transformPtr( iTransformBlock->Des() );

    TInt offset( 0 );
    while ( offset <= bufSize - blocksize )
        {
        transformPtr = buf.Mid( offset, blocksize );
        iDecryptor->Transform( transformPtr );
        decPtr.Append( transformPtr );
        offset += blocksize;
        }

    // Remove padding nulls from end of the decrypted password
    if ( remainder != 0 )
        {
        transformPtr = buf.Mid( offset );
        transformPtr.AppendFill( KPad, blocksize - remainder );
        iDecryptor->Transform( transformPtr );
        decPtr.Append( transformPtr );
        }

    TInt padStart( decrypted->Des().Locate( KPad ) );
    if ( padStart != KErrNotFound )
        {
        decrypted->Des().SetLength( padStart );
        }

    CleanupStack::Pop( decrypted );
    return decrypted;
    }

// -----------------------------------------------------------------------------
// CIMPSSAPSecurer::FetchIMEI()
//
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CIMPSSAPSecurer::FetchIMEI( TPtr8& aImei )
    {

    // Create a fake serial number for emulator or for fallback if
    // we're unable to get the real IMEI from hardware
    TBuf<RMobilePhone::KPhoneSerialNumberSize> fakeSerialNumber( KSAPFakeIMEI );
    aImei.Copy( fakeSerialNumber );


#ifndef __WINS__
    RMobilePhone::TMobilePhoneIdentityV1 phoneIdentity;
    // initializations
    RMobilePhone phone;
    RTelServer server;

    TRAPD( err,
        {
        err = server.Connect();
        User::LeaveIfError( err );
        CleanupClosePushL( server );

        err = server.LoadPhoneModule( KMmTsyModuleName );
        if ( err != KErrNone && err != KErrAlreadyExists )
            {
            User::Leave( err );
            }
        err = phone.Open( server, KMmTsyPhoneName );
        User::LeaveIfError( err );
        CleanupClosePushL( phone );

        TUint32 identityCaps;
        err = phone.GetIdentityCaps( identityCaps );
        User::LeaveIfError( err );

        if ( identityCaps & RMobilePhone::KCapsGetModel )
            {
            TRequestStatus status;
            phone.GetPhoneId( status, phoneIdentity );
            // No choice but to wait for the request to complete.
            User::WaitForRequest( status ); // CSI: 94 #
            User::LeaveIfError( status.Int() ); // CSI: 42 #
            // Inside trap
            }
        else // In case we didn't have capabilities to get real IMEI
            {
            User::Leave( KErrNotSupported ); // CSI: 42 #
            // Inside trap
            }

        CleanupStack::PopAndDestroy( 2 ); // server, phone
        } );

    // Fetching the IMEI went fine.
    if ( err == KErrNone )
        {
        aImei.Copy( phoneIdentity.iSerialNumber );
        }

#endif // __WINS__

    }


// -----------------------------------------------------------------------------
// CIMPSSAPSecurer::GetPwdKeyL()
// Generates new the encryption key
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CIMPSSAPSecurer::GetPwdKeyL( TPtr8& aKey )
    {
    // Copy the defined key
    aKey.Copy( KSAPPwdDefinedKey );

    // Fetch the IMEI
    HBufC8* imeiBuf = HBufC8::NewLC( RMobilePhone::KPhoneSerialNumberSize );
    TPtr8 imeiPtr = imeiBuf->Des();
    FetchIMEI( imeiPtr );

    // XOR defined key with IMEI
    TText8* character = ( TText8* ) aKey.Ptr();
    TText8* characterEnd = aKey.Length() + ( TText8* ) aKey.Ptr();
    TText8 asNumber;

    const TInt imeiLen = imeiPtr.Length();
    TInt encryptCharIndex = 0;
    for ( ; character < characterEnd; character++ )
        {
        asNumber = *character;
        TInt imeiIndex( encryptCharIndex % imeiLen );
        asNumber ^= imeiPtr[ imeiIndex ];
        *character = asNumber;

        encryptCharIndex++;
        }

    CleanupStack::PopAndDestroy( imeiBuf );
    }


// End of File