cms/src/CCMSAuthenticatedData.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 15:20:08 +0200
changeset 0 164170e6151a
permissions -rw-r--r--
Revision: 201004

/*
* Copyright (c) 2002 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    "CCMSAuthenticatedData.h"
#include "CCMSX509AlgorithmIdentifier.h"
#include "CCMSOriginatorInfo.h"
#include "CCMSRecipientInfo.h"
#include "CCMSKeyTransRecipientInfo.h"
#include "CCMSKeyAgreeRecipientInfo.h"
#include "CCMSKEKRecipientInfo.h"
#include "CCMSAttribute.h"
#include "CCMSX509Certificate.h"
#include "CCMSCertificateChoices.h"
#include "CCMSX509CertificateList.h"
#include <asn1dec.h>
#include <asn1enc.h>

// CONSTANTS
const TInt KDefaultGranularity = 1;
const TInt KMinNumberOfSubModules = 5;
const TInt KMaxNumberOfSubModules = 9;
const TTagType KOriginatorInfoTag = 0;
const TTagType KDigestAlgorithmTag = 1;
const TTagType KAuthenticatedAttributesTag = 2;
const TTagType KUnauthenticatedAttributesTag = 3;

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

// Destructor
CCMSAuthenticatedData::CAuthenticatedDataData::~CAuthenticatedDataData()
    {
    delete iOriginatorInfo;
    if( iRecipientInfos )
        {
        iRecipientInfos->ResetAndDestroy();
        delete iRecipientInfos;
        }
    delete iMacAlgorithm;
    delete iDigestAlgorithm;
    delete iEncapContentInfo;
    if( iAuthenticatedAttributes )
        {
        iAuthenticatedAttributes->ResetAndDestroy();
        delete iAuthenticatedAttributes;
        }
    delete iMac;
    if( iUnauthenticatedAttributes )
        {
        iUnauthenticatedAttributes->ResetAndDestroy();
        delete iUnauthenticatedAttributes;
        }
    }

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

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
EXPORT_C void CCMSAuthenticatedData::ConstructL(
    CArrayPtr< CCMSRecipientInfo >* aRecipientInfos,
    CCMSX509AlgorithmIdentifier* aMacAlgorithm,
    CCMSEncapsulatedContentInfo* aEncapContentInfo,
    const TDesC8& aMac )
    {
    iData = new( ELeave ) CAuthenticatedDataData;
    iData->iMac = aMac.AllocL();
    
    // all memory allocations have been done, we can take ownerships
    iData->iRecipientInfos = aRecipientInfos;
    iData->iMacAlgorithm = aMacAlgorithm;
    iData->iEncapContentInfo = aEncapContentInfo;
    }

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
EXPORT_C void CCMSAuthenticatedData::ConstructL( )
    {
    // creating empty/default values
    iData = new( ELeave ) CAuthenticatedDataData;
    iData->iRecipientInfos =
        new( ELeave ) CArrayPtrFlat< CCMSRecipientInfo >( KDefaultGranularity );
    iData->iMacAlgorithm = CCMSX509AlgorithmIdentifier::NewL();
    iData->iEncapContentInfo = CCMSEncapsulatedContentInfo::NewL();
    iData->iMac = KNullDesC8().AllocL();
    }
    

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CCMSAuthenticatedData*
CCMSAuthenticatedData::NewLC()
	{
	// creating with empty values
    CCMSAuthenticatedData* self =
        new( ELeave ) CCMSAuthenticatedData();
    CleanupStack::PushL( self );
    self->ConstructL( );
	return self;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CCMSAuthenticatedData*
CCMSAuthenticatedData::NewLC(
    CArrayPtr< CCMSRecipientInfo >* aRecipientInfos,
    CCMSX509AlgorithmIdentifier* aMacAlgorithm,
    CCMSEncapsulatedContentInfo* aEncapContentInfo,
    const TDesC8& aMac )
    {
    CCMSAuthenticatedData* self =
        new( ELeave ) CCMSAuthenticatedData();
    CleanupStack::PushL( self );
    self->ConstructL( aRecipientInfos, aMacAlgorithm, aEncapContentInfo, aMac );

    return self;
    }

// Destructor
CCMSAuthenticatedData::~CCMSAuthenticatedData()
    {
	delete iData;
    }

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::DecodeL
// Decrypts raw data to this instance
// -----------------------------------------------------------------------------
void CCMSAuthenticatedData::DecodeL( const TDesC8& aRawData )
	{
    CArrayPtr< TASN1DecGeneric >* items = DecodeSequenceLC(
        aRawData, KMinNumberOfSubModules, KMaxNumberOfSubModules );

    // now we know that there are at least 5 items
    TInt itemCount = items->Count();
    __ASSERT_DEBUG( itemCount >= KMinNumberOfSubModules, User::Invariant() );
    
    TInt sequenceCounter = 0;

    CAuthenticatedDataData* data = new( ELeave ) CAuthenticatedDataData;
    CleanupStack::PushL( data );
    
    // decode version
    TASN1DecInteger intDecoder;
    data->iVersion =
        intDecoder.DecodeDERShortL( *items->At( sequenceCounter++ ) );

    // decode originatorInfo, if exist
    TASN1DecGeneric* originatorInfoDecoder = items->At( sequenceCounter );
    if( originatorInfoDecoder->Tag() == KOriginatorInfoTag )
        {
        data->iOriginatorInfo = CCMSOriginatorInfo::NewL();
        data->iOriginatorInfo->DecodeImplicitTagL(
            originatorInfoDecoder->Encoding(), KOriginatorInfoTag );
        sequenceCounter++;
        }

    // decode recipientInfos
    CArrayPtr< TASN1DecGeneric >* recipientInfos = DecodeSequenceLC(
        items->At( sequenceCounter++)->Encoding() );
    TInt recipientInfoCount = recipientInfos->Count();
    data->iRecipientInfos =
        new( ELeave ) CArrayPtrFlat< CCMSRecipientInfo >( recipientInfoCount );
    for( TInt i = 0; i < recipientInfoCount; i++ )
        {
        TASN1DecGeneric* recipientInfoDecoder = recipientInfos->At( i );
        CCMSRecipientInfo* recipientInfo = NULL;
        switch( recipientInfoDecoder->Tag() )
            {
            case EASN1Sequence:
                {
                recipientInfo = CCMSKeyTransRecipientInfo::NewLC();
                recipientInfo->DecodeL( recipientInfoDecoder->Encoding() );
                break;
                }
            case KCMSKeyAgreeRecipientInfoTag:
                {
                recipientInfo = CCMSKeyAgreeRecipientInfo::NewLC();
                recipientInfo->DecodeL( recipientInfoDecoder->Encoding() );
                break;
                }
            case KCMSKEKRecipientInfoTag:
                {
                recipientInfo = CCMSKEKRecipientInfo::NewLC();
                recipientInfo->DecodeL( recipientInfoDecoder->Encoding() );
                break;
                }
            default:
                {
                User::Leave( KErrArgument );
                }
            }
        data->iRecipientInfos->AppendL( recipientInfo );
        CleanupStack::Pop( recipientInfo );
        }
    CleanupStack::PopAndDestroy( recipientInfos );
    
    // decode macAlgorithm
    data->iMacAlgorithm = CCMSX509AlgorithmIdentifier::NewL();
    data->iMacAlgorithm->DecodeL( items->At( sequenceCounter++)->Encoding() );

    // decode digestAlgorithm, if exist
    TASN1DecGeneric* digestAlgorithmDec = items->At( sequenceCounter );
    if( digestAlgorithmDec->Tag() == KDigestAlgorithmTag )
        {
        data->iDigestAlgorithm = CCMSX509AlgorithmIdentifier::NewL();
        data->iDigestAlgorithm->DecodeL( digestAlgorithmDec->GetContentDER() );
        sequenceCounter++;
        }

    // decode encapContentInfo
    if( sequenceCounter == itemCount )
        {
        User::Leave( KErrArgument );
        }
    data->iEncapContentInfo = CCMSEncapsulatedContentInfo::NewL();
    data->iEncapContentInfo->DecodeL(
        items->At( sequenceCounter++)->Encoding() );

    // decode authenticatedAttributes, if exist
    if( sequenceCounter == itemCount )
        {
        User::Leave( KErrArgument );
        }
    TASN1DecGeneric* authAttributesDec = items->At( sequenceCounter );
    if( authAttributesDec->Tag() == KAuthenticatedAttributesTag )
        {
        data->iAuthenticatedAttributes = DecodeAttributesL( authAttributesDec );
        sequenceCounter++;
        }

    // decode mac
    if( sequenceCounter == itemCount )
        {
        User::Leave( KErrArgument );
        }
    TASN1DecOctetString octetStrDec;
    data->iMac = octetStrDec.DecodeDERL( *( items->At( sequenceCounter++ ) ) );

    // decode unauthenticatedAttributes, if exist
    if( itemCount > sequenceCounter )
        {
        TASN1DecGeneric* unauthAttributesDec = items->At( sequenceCounter );
        if( unauthAttributesDec->Tag() != KUnauthenticatedAttributesTag )
            {
            User::Leave( KErrArgument );
            }
        data->iUnauthenticatedAttributes =
            DecodeAttributesL( unauthAttributesDec );
        }

    // all done, change state
    CleanupStack::Pop( data );
    CleanupStack::PopAndDestroy( items );
    delete iData;
    iData = data;
	}




// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::EncoderLC
// Returns ASN1 encoder for this instance
// -----------------------------------------------------------------------------
CASN1EncBase* CCMSAuthenticatedData::EncoderLC() const
	{
    CASN1EncSequence* root = CASN1EncSequence::NewLC();

    // encode version
    CASN1EncInt* version = CASN1EncInt::NewLC( iData->iVersion );
    root->AddAndPopChildL( version );

    // encode originatorInfo, if exist
    if( iData->iOriginatorInfo )
        {
        CASN1EncBase* originatorInfo = iData->iOriginatorInfo->EncoderLC();
        originatorInfo->SetTag( KOriginatorInfoTag );
        root->AddAndPopChildL( originatorInfo );
        }

    // encode recipientInfos ::= SET OF RecipientInfo
    CASN1EncSequence* recipientInfos = CASN1EncSequence::NewLC();
    TInt recipientInfoCount = iData->iRecipientInfos->Count();
    TInt i = 0;
    for( ; i < recipientInfoCount; i++ )
        {
        CASN1EncBase* recipientInfo =
            iData->iRecipientInfos->At( i )->TaggedEncoderLC();
        recipientInfos->AddAndPopChildL( recipientInfo );
        }
    recipientInfos->SetTag( EASN1Set, EUniversal );
    root->AddAndPopChildL( recipientInfos );
    
    // encode macAlgorithm
    CASN1EncBase* macAlgorithm = iData->iMacAlgorithm->EncoderLC();
    root->AddAndPopChildL( macAlgorithm );

    // encode digestAlgorithm, if exist
    if( iData->iDigestAlgorithm )
        {
        CASN1EncBase* digestAlgorithm = iData->iDigestAlgorithm->EncoderLC();
        CleanupStack::Pop( digestAlgorithm );
        
        // CASN1EncExplicitTag takes ownership of the parameter, even
        // if the method leaves.
        CASN1EncExplicitTag* taggedDigestAlgorithm =
            CASN1EncExplicitTag::NewLC( digestAlgorithm, KDigestAlgorithmTag );
        root->AddAndPopChildL( taggedDigestAlgorithm );
        }

    // encode encapContentInfo
    CASN1EncBase* encapContentInfo = iData->iEncapContentInfo->EncoderLC();
    root->AddAndPopChildL( encapContentInfo );

    // encode authenticatedAttributes, if exist
    if( iData->iAuthenticatedAttributes )
        {
        CASN1EncSequence* authAttributes = CASN1EncSequence::NewLC();
        TInt authAttributeCount = iData->iAuthenticatedAttributes->Count();
        for( i = 0; i < authAttributeCount; i++ )
            {
            CASN1EncBase* attribute =
                iData->iAuthenticatedAttributes->At( i )->EncoderLC();
            authAttributes->AddAndPopChildL( attribute );
            }
        authAttributes->SetTag( KAuthenticatedAttributesTag );
        root->AddAndPopChildL( authAttributes );
        }

    // encode mac
    CASN1EncOctetString* mac = CASN1EncOctetString::NewLC( *iData->iMac );
    root->AddAndPopChildL( mac );
    
    // encode unauthenticatedAttributes, if exist
    if( iData->iUnauthenticatedAttributes )
        {
        CASN1EncSequence* unauthAttributes = CASN1EncSequence::NewLC();
        TInt unauthAttributeCount = iData->iUnauthenticatedAttributes->Count();
        for( i = 0; i < unauthAttributeCount; i++ )
            {
            CASN1EncBase* attribute =
                iData->iUnauthenticatedAttributes->At( i )->EncoderLC();
            unauthAttributes->AddAndPopChildL( attribute );
            }
        unauthAttributes->SetTag( KUnauthenticatedAttributesTag );
        root->AddAndPopChildL( unauthAttributes );
        }
    
    return root;
    }

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::Version()
// Getter for Version
// -----------------------------------------------------------------------------
EXPORT_C TInt CCMSAuthenticatedData::Version() const
	{
	return iData->iVersion;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::OriginatorInfo()
// Getter for OriginatorInfo
// -----------------------------------------------------------------------------
EXPORT_C const CCMSOriginatorInfo* CCMSAuthenticatedData::OriginatorInfo() const
	{
	return iData->iOriginatorInfo;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::RecipientInfos()
// Getter for recipientInfos
// -----------------------------------------------------------------------------
EXPORT_C const CArrayPtr< CCMSRecipientInfo >&
CCMSAuthenticatedData::RecipientInfos() const
	{
	return *( iData->iRecipientInfos );
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::MacAlgorithm()
// Getter for macAlgorithm
// -----------------------------------------------------------------------------
EXPORT_C const CCMSX509AlgorithmIdentifier&
CCMSAuthenticatedData::MacAlgorithm() const
	{
	return *( iData->iMacAlgorithm );
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::DigestAlgorithm()
// Getter for digestAlgorithm
// -----------------------------------------------------------------------------
EXPORT_C const CCMSX509AlgorithmIdentifier*
CCMSAuthenticatedData::DigestAlgorithm() const
	{
	return iData->iDigestAlgorithm;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::EncapContentInfo()
// Getter for encapContentInfo
// -----------------------------------------------------------------------------
EXPORT_C const CCMSEncapsulatedContentInfo&
CCMSAuthenticatedData::EncapContentInfo() const
	{
	return *( iData->iEncapContentInfo );
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::AuthenticatedAttributes()
// Getter for authenticatedAttributes
// -----------------------------------------------------------------------------
EXPORT_C const CArrayPtr< CCMSAttribute >*
CCMSAuthenticatedData::AuthenticatedAttributes() const
	{
	return iData->iAuthenticatedAttributes;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::Mac()
// Getter for mac
// -----------------------------------------------------------------------------
EXPORT_C const TDesC8& CCMSAuthenticatedData::Mac() const
	{
	return *( iData->iMac );
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::UnauthenticatedAttributes()
// Getter for unauthenticatedAttributes
// -----------------------------------------------------------------------------
EXPORT_C const CArrayPtr< CCMSAttribute >*
CCMSAuthenticatedData::UnauthenticatedAttributes() const
	{
	return iData->iUnauthenticatedAttributes;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetVersion()
// Setter for version
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetVersion( TInt aVersion )
	{
    iData->iVersion = aVersion;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetOriginatorInfoL()
// Setter for OriginatorInfo
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetOriginatorInfoL(
    CCMSOriginatorInfo* aOriginatorInfo )
	{
    delete iData->iOriginatorInfo;
    iData->iOriginatorInfo = aOriginatorInfo;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetRecipientInfosL()
// Setter for recipientInfos
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetRecipientInfosL(
    CArrayPtr< CCMSRecipientInfo >* aRecipientInfos )
	{
    if( ( !aRecipientInfos ) || ( aRecipientInfos->Count() == 0 ) )
        {
        User::Leave( KErrArgument );
        }
    
    if( iData->iRecipientInfos )
        {
        iData->iRecipientInfos->ResetAndDestroy();
        delete iData->iRecipientInfos;
        }
    iData->iRecipientInfos = aRecipientInfos;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetMacAlgorithmL()
// Setter for macAlgorithm
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetMacAlgorithmL(
    CCMSX509AlgorithmIdentifier* aMacAlgorithm )
	{
    if( !aMacAlgorithm )
        {
        User::Leave( KErrArgument );
        }
    delete iData->iMacAlgorithm;
    iData->iMacAlgorithm = aMacAlgorithm;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetDigestAlgorithmL()
// Setter for digestAlgorithm
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetDigestAlgorithmL(
    CCMSX509AlgorithmIdentifier* aDigestAlgorithm )
	{
    delete iData->iDigestAlgorithm;
    iData->iDigestAlgorithm = aDigestAlgorithm;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetEncapContentInfoL()
// Setter for encapContentInfo
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetEncapContentInfoL(
    CCMSEncapsulatedContentInfo* aEncapContentInfo )
	{
    if( !aEncapContentInfo )
        {
        User::Leave( KErrArgument );
        }
    delete iData->iEncapContentInfo;
    iData->iEncapContentInfo = aEncapContentInfo;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetAuthenticatedAttributesL()
// Setter for authenticatedAttributes
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetAuthenticatedAttributesL(
    CArrayPtr< CCMSAttribute >* aAuthenticatedAttributes )
	{
    if( iData->iAuthenticatedAttributes )
        {
        iData->iAuthenticatedAttributes->ResetAndDestroy();
        delete iData->iAuthenticatedAttributes;
        }
    iData->iAuthenticatedAttributes = aAuthenticatedAttributes;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetMacL
// Setter for mac
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetMacL(
    const TDesC8& aMac)
	{
    HBufC8* mac = aMac.AllocL();
    delete iData->iMac;
    iData->iMac = mac;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::SetUnauthenticatedAttributesL()
// Setter for unauthenticatedAttributes
// -----------------------------------------------------------------------------
EXPORT_C void CCMSAuthenticatedData::SetUnauthenticatedAttributesL(
    CArrayPtr< CCMSAttribute >* aUnauthenticatedAttributes )
	{
    if( iData->iUnauthenticatedAttributes )
        {
        iData->iUnauthenticatedAttributes->ResetAndDestroy();
        delete iData->iUnauthenticatedAttributes;
        }
    iData->iUnauthenticatedAttributes = aUnauthenticatedAttributes;
	}

// -----------------------------------------------------------------------------
// CCMSAuthenticatedData::DecodeAttributesL
// Decodes an array of attributes
// -----------------------------------------------------------------------------
CArrayPtrFlat< CCMSAttribute >* CCMSAuthenticatedData::DecodeAttributesL(
    TASN1DecGeneric* aAttributesDec ) // generic decoder for the sequence
    {
    TASN1DecSequence sequenceDecoder;
    CArrayPtr< TASN1DecGeneric >* attributes =
        sequenceDecoder.DecodeDERLC( *aAttributesDec );
    TInt attributeCount = attributes->Count();
    if( attributeCount <  1 )
        {
        User::Leave( KErrArgument );
        }
    CArrayPtrFlat< CCMSAttribute >* retVal =
        new( ELeave ) CArrayPtrFlat< CCMSAttribute >( attributeCount );
    CleanupStack::PushL( retVal );
    for( TInt i = 0; i < attributeCount; i++ )
        {
        CCMSAttribute* attribute = CCMSAttribute::NewLC();
        attribute->DecodeL( attributes->At( i )->Encoding() );
        retVal->AppendL( attribute );
        // attribute is left in cleanup stack, as retVal has not been pushed
        // with ResetAndDestroyPushL
        }
    CleanupStack::Pop( attributeCount ); // all attributes
    CleanupStack::Pop( retVal );
    CleanupStack::PopAndDestroy( attributes );
    return retVal;
    }

//  End of File