pkiutilities/PKCS12/CrBer/Src/crber.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) 2000, 2004 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 module contains the implementation of CCrBer class. 
*
*/



//  INCLUDE FILES
#include "crber.h"
#include <e32math.h>    // Pow


// -----------------------------------------------------------------------------
// CCrBer
// Constructor 
// This function constructs CCrBer object
// -----------------------------------------------------------------------------
CCrBer::CCrBer(TInt aLevel /* = 0 */)
    {
    TReal size = 0;
    
    Math::Pow(size, 256, sizeof(TUint));
    iMaxUint = STATIC_CAST(TUint, size - 1);
    
    Math::Pow(size, 128, sizeof(TInt));
    iMaxInt = STATIC_CAST(TInt, size - 1);
    
    
    iEOCBytes[0] = 0x00;
    iEOCBytes[1] = 0x00;

    iType = KBerUnknown;
    
    iIndefinite = EFalse;

    iObjectBegin = 0;
    iContentBegin = 0;
    iContentLen = 0;
    iObjectLen = 0;

    iLevel = aLevel;

    iData = NULL;
    }

// -----------------------------------------------------------------------------
// CCrBer
// Destructor 
// This function destructs CCrBer object
// -----------------------------------------------------------------------------
EXPORT_C CCrBer::~CCrBer()
    {
    iData = NULL;
	iInt.Close();
    }

// -----------------------------------------------------------------------------
// CCrBer::ConstructL
// This function initializes CCrBer object's member objects.
// -----------------------------------------------------------------------------
TAny CCrBer::ConstructL()
    {
    }
// -----------------------------------------------------------------------------
// CCrBer::NewLC
// -----------------------------------------------------------------------------
EXPORT_C CCrBer* CCrBer::NewLC(TInt aLevel /* = 0 */)
    {
    CCrBer* self = new (ELeave) CCrBer(aLevel);
    CleanupStack::PushL(self);

    self->ConstructL();

    return self; 
    }

// -----------------------------------------------------------------------------
// CCrBer::NewL
// -----------------------------------------------------------------------------
EXPORT_C CCrBer* CCrBer::NewL(TInt aLevel /* = 0 */)
    {
    CCrBer* self = NewLC(aLevel);
    CleanupStack::Pop();

    return self; 
    }

// -----------------------------------------------------------------------------
// CCrBer::Read
// Read next BER encoded object from the current position of
// given CCrData to this object. Return the type of the BER
// object, or KBerUnknown, if not of any known type. Only pointer
// to aData is stored into this object, so Get* functions are
// meaningful only if original data object is still existing,
// when these functions are used.
// -----------------------------------------------------------------------------
EXPORT_C TUint8 CCrBer::Read(CCrData* aData)
    {
    if ((iType = ReadType(aData)) != KBerUnknown)
        {
        TInt  move;
        TInt  pos = 0;
        TBool conLenKnown;


        // If type is known, this object begins right here,
        // well, to be exact, one byte before this point.
        if ((aData->Seek(ESeekCurrent, pos)) == KErrNone)
            {
            conLenKnown = ETrue;

            // Now we have at least something sensible. Store pointer to
            // the data object (and hope that the caller doesn't delete it :)
            iData = aData;

            iObjectBegin = pos - 1;

            // Read length.
            iContentLen = ReadLen(aData, iIndefinite, &iLenLen);

            // Content begins right after type tag and length bytes.
            iContentBegin = pos + iLenLen;

            // If length is indefinite and type isn't set, sequence,
            // or explicit/implicit constructed, find next end-of-content
            // tag to define exact length.
            if (iIndefinite)
                {
                if ((iType != KBerSeq) &&
                    (iType != KBerSet) &&
                    (iType != KBerImplicitConstructed) &&
                    (iType != KBerExplicitConstructed))
                    {
                    // Give special treatment to constructed encoding.
                    if ((iType & KBerConstructedBit) ||
                        (iType & KBerImplicitConstructed))
                        {
                        iContentLen = OpenConstructedEncodingWithTagL(
                                        aData, *this);
                        
                        }
                    else
                        {
                        iContentLen = FindEndOfContent(aData);
                        }
                    }
                else
                    {
                    // We really can't know what the length is,
                    // until we open up the whole inner content.
                    conLenKnown = EFalse;
                    }
                }

            // Now, if we know content length, then we can calculate whole
            // object's length; it is tag + length bytes + content length.
            if (conLenKnown)
                {
                SetObjectLen();

                // Also move data pointer at the end of this object, except
                // if object was set or sequence, in which case don't move,
                // because we still have to open inner items.
                // At indefinite case this is already done (other than
                // sequence or set) or this can't be done (sequence or
                // set). So, if not indefinite and not sequence or set,
                // move data pointer the amount of content length.
                if (!(iIndefinite) && !(IsSeqOrSet(iType)))
                    {
                    move = iContentLen;

                    aData->Seek(ESeekCurrent, move);
                    }
                }

            // If tag was end-of-content tag, check that also length
            // was 0 and not indefinite, this guarantees that we really
            // have an end-of-content tag (00 00).
            if (iType == KBerEndOfContent)
                {
                if ((iContentLen != 0) || (iIndefinite))
                    {
                    iType = KBerUnknown;
                    }
                }
            }
        
	
	 
		}
    return iType;
    }



// -----------------------------------------------------------------------------
// CCrBer::ReadType
// Read type tag from current position in given CCrData.
// Returns type tag or KBerUnknown, if not of any known type.
// -----------------------------------------------------------------------------
EXPORT_C TUint8 CCrBer::ReadType(CCrData* aData)
    {
    TBuf8<1> byte;
    TUint8   type = KBerUnknown;   // By default we are pessimists.

    // Read type.
    if ((aData != 0) &&
        (aData->Read(byte, 1) == KErrNone) &&
        (byte.Length() > 0))
        {
        type = byte[0];

        if (!IsKnownType(type))
            {
            // Don't let type to be whatever byte happened to be
            // at that place. Set it to unknown, which we all know.
            type = KBerUnknown;
            }
        }

    return type;
    }

// -----------------------------------------------------------------------------
// CCrBer::ReadLen
// Read length tags from current position in given CCrData.
// Returns length. If length is indefinite, aIndefinite is set
// to true, otherwise to false. In indefinite case length is 0.
// Also sets amount of length bytes in aLenLen, if given.
// -----------------------------------------------------------------------------
EXPORT_C TUint CCrBer::ReadLen(
    CCrData* aData,
    TBool&   aIndefinite,
    TUint8*  aLenLen/* = 0 */)
    {
    TBuf8<LEN_BYTES_MAX> bytes;
    TUint8               byte = 0;
    TUint                len = 0;

    // Originally assume that length is definite,
    aIndefinite = EFalse;

    // First byte tells if the length bytes are in short or in long form.
    if ((aData != 0) && (aData->Read(bytes, 1) == KErrNone))
        {
        if (bytes.Length() <= 0)        
            {
            User::Leave(KErrArgument);
            }
        byte = bytes[0];

        // We have at least one length byte.
        if (aLenLen != 0)
            {
            *aLenLen = 1;
            }

        if (byte & KBerLongLengthBit)
            {
            // We have length bytes, but how many?
            TUint8 lenBytes = (TUint8)(byte & ~KBerLongLengthBit);

            // If length is in long form, but there are zero
            // length bytes, then length is indefinite.
            if (lenBytes == 0)
                {
                aIndefinite = ETrue;
                }
            else
                {
                if (aLenLen != 0)
                    {
                    // Add amount of actual length bytes to one,
                    // which was for long length form byte.
                    for (TInt i = 0; i < lenBytes; i++)
                        {
                        (*aLenLen)++;
                        }
					}

                // Otherwise we have to interpret length bytes and
                // move the result into len variable. First check
                // that there aren't more bytes than fits to
                // unsigned integer, we don't want any troubles here.
                if (lenBytes > sizeof(TUint))
                    {
                    // Return max uint, caller can then decide
                    // what to do with this huge pile of...
                    return iMaxUint;
                    }

                // Read length bytes
                if (aData->Read(bytes, lenBytes) == KErrNone)
                    {
                    TUint8 i;

                    // and move them to len.
                    for (i = 0; i < lenBytes; i++)
                        {
                        len = len << 8;

                        len += bytes[i];
                        }
                    }
                }
            }
        else
            {
            // Otherwise length was in short form and length
            // byte alone tells us the length of the contens.
            len = byte;
            }
        }

    return len;
    }


// -----------------------------------------------------------------------------
// CCrBer::IsKnownType
// Returns true if given BER tag is identified one.
// Returns:  ETrue of EFalse.
// -----------------------------------------------------------------------------
EXPORT_C TBool CCrBer::IsKnownType(TBerTag aTag)
    {
    TBool isKnown = EFalse;

    // Remove constructed bit, if it is on without other upper byte tags.
    if ((aTag & 0xF0) == KBerConstructedBit)
        {
        aTag &= ~KBerConstructedBit;
        }

    // Remove implicit/explicit constructed bit, 
    // if it is on without other upper byte tags.
    if ((aTag & 0xF0) == KBerImplicitConstructed)
        {
        aTag &= ~KBerImplicitConstructed;
        }

    switch (aTag)
        {
        case KBerEndOfContent:
        case KBerBoolean:
        case KBerInteger:
        case KBerBitString:
        case KBerOctetString:
        case KBerNull:
        case KBerOid:
		case KBerNumS:
        case KBerPrS:
        case KBerT61S:
		case KBerVideoS:
        case KBerIA5S:
        case KBerUtc:
		case KBerGenTime:                                
		case KBerGraphS: 
		case KBerVisibleS:
		case KBerGeneralS:
        case KBerBmpS:
        case KBerSeq:
        case KBerSet:
        case KBerImplicitConstructed:
        // Same as KBerExplicitConstructed
        case KBerImplicit:
        // Same as KBerExplicit
            {
            isKnown = ETrue;
            break;
            }
        default:
            {
            isKnown = EFalse;
            break;
            }
        }

    return isKnown;
    }



// -----------------------------------------------------------------------------
// CCrBer::IsSeqOrSet
// Returns true if given BER tag is set, sequence,
// implicit contructed, or explicit constructed tag.
// -----------------------------------------------------------------------------
EXPORT_C TBool CCrBer::IsSeqOrSet(TBerTag aTag)
    {
    TBool isSeqOrSet = EFalse;

    if ((aTag == KBerSeq) ||
        (aTag == KBerSet) ||
        (aTag == KBerImplicit) ||
        (aTag == KBerExplicit) ||
        (aTag == KBerImplicitConstructed) ||
        (aTag == KBerExplicitConstructed))

        {
        isSeqOrSet = ETrue;
        }

    return isSeqOrSet;
    }

// -----------------------------------------------------------------------------
// CCrBer::FindEndOfContent
// Finds next end-of-content (00 00) tag from given data.
// Returns the distance between current place and the tag,
// or 0, if not found. Moves data pointer to the next byte
// _after_ the tag, i.e. two bytes longer than you might
// except from the return value.
// -----------------------------------------------------------------------------
EXPORT_C TUint CCrBer::FindEndOfContent(CCrData* aData)
    {
    TBool go = ETrue;
    TInt bufferOffset = 0;
    TInt dataOffset = 0;
    TInt move = 0;

    TBuf8<KReadBufMax> bytes;

    if (aData == 0)
        {
        return dataOffset;
        }

    // Read buffer of data. Go on, if there is something to go with.
    while ((aData->Read(bytes, KReadBufMax) == KErrNone) &&
           (bytes.Length() != 0) && go)
        {
        TBuf8<2> EOCBytes;

        EOCBytes.Append(iEOCBytes[0]);
        EOCBytes.Append(iEOCBytes[1]);

        // Try to find end-of-content tag.
        bufferOffset = bytes.Find(EOCBytes);

        // If found, move data pointer right _after_
        // the place of founded tag, and break.
        if (bufferOffset != KErrNotFound)
            {
            move = bufferOffset -
                       bytes.Length() +
                       EOCBytes.Length();

            aData->Seek(ESeekCurrent, move);

            dataOffset += bufferOffset;

            go = EFalse;                    //break;
            }
        else
            {
            // Otherwise keep searching. First check that the last
            // character of the buffer isn't 00. If it is, move the
            // data pointer one byte backwards to prevent us from
            // missing end-of-content tag, if it is divided between
            // buffers.
            if (bytes[bytes.Length() - 1] == KBerEndOfContent)
                {
                move = -1;

                aData->Seek(ESeekCurrent, move);

                dataOffset--;
                }

            dataOffset += bytes.Length();
            }
        }

    // If nothing was found, move data pointer back
    // to where it was and return 0.
    if (bytes.Length() == 0)
        {
        dataOffset = -dataOffset;

        aData->Seek(ESeekCurrent, dataOffset);

        dataOffset = 0;
        }

    return dataOffset;
    }

// -----------------------------------------------------------------------------
// CCrBer::OpenConstructedEncodingL
// Open constructed encoding from this object.  
// Parameters: aTarget; target for contentbytes.
// Return Values:  Number of objects in this contructed object.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::OpenConstructedEncodingL(CCrData& aTarget)
    {      
    TInt err = KErrNone;
    TInt count = 0;
    TInt offset = iContentBegin;
    TInt objectNum = 0;
    TInt type = Type();
    CCrBer* object = NULL;

    if (type <= KBerConstructed)        // not valid type
        {
        User::Leave(KErrArgument);
        }
    else  
        {
        type -= KBerConstructed;        // type what we are looking for
        }

    CCrBerSet* newSet = CCrBerSet::NewL(1);
    CleanupStack::PushL(newSet);
    iData->Seek(ESeekStart, offset);    // seek right place; content begin
    newSet->OpenL(iData, KOpenAllLevels);
    count = newSet->Count();            

    HBufC8* obj = NULL;                 // buffer for CCrBer-objects

    for (objectNum = 0; (objectNum < count); objectNum++)
        {
        object = newSet->At(objectNum); // select object
        
        if (object->Type() == type)
            {
            obj = HBufC8::NewLC(object->ContentLen());
            TPtr8 pObj  = obj->Des();
            
            err = iData->Read(object->ContentBegin(), pObj, object->ContentLen());
            
            if (err < KErrNone)         // if error -> leave
                {
                CleanupStack::PopAndDestroy(2);  // delete newSet, obj;
                User::Leave(err);
                }    
            err = aTarget.Write(pObj);  // write content to CCrData  
            
            CleanupStack::PopAndDestroy();  // delete obj;
            obj = NULL;
            
            if (err < KErrNone)         // if error -> leave
                {
                CleanupStack::PopAndDestroy();  // delete newSet;
                User::Leave(err);
                }
            
            }
        else 
            {
            count = objectNum;
            }
        }
    CleanupStack::PopAndDestroy();      // delete newSet;

    return count;
    }

// -----------------------------------------------------------------------------
// CCrBer::OpenConstructedEncodingWithTagL
// Open constructed encoding with given tag from given data.
// Add all founded octets into the parameter string, if given.
// Return amount of bytes read.
// -----------------------------------------------------------------------------
EXPORT_C TUint CCrBer::OpenConstructedEncodingWithTagL(
    CCrData* aData,
    CCrBer&  parentObj,
    HBufC8*  aBuf /* = 0 */)
    {
    TInt    read = 0;
    CCrBer  temp;
    TBerTag parentTag = KBerUnknown;
    TBerTag tempTag   = KBerUnknown;
    HBufC8* tempBuf   = NULL;

    parentTag = parentObj.Type();

    // Check given object. It should have constructed tag.
    if (parentTag & KBerConstructedBit)
        {
        TUint len = 0;
        TUint totalLen = iMaxUint;
        TBool isIndefinite = parentObj.Indefinite();

        TBufC8<4> buf = _L8("Test");
        TPtr8     ptr = buf.Des();

        if (aBuf != 0)
            {
            ptr = aBuf->Des();
            }

        tempBuf = HBufC8::NewLC(KReadBufMax);

        // After that we know that object either contains length or
        // it is indefinite. Set max int to len even in the case of
        // indefinite length to prevent this loop from going on forever.
        if (!isIndefinite)
            {
            totalLen = parentObj.ContentLen();
            }

        while (len < totalLen)
            {
            // Read objects one by one, calculate content lengths together,
            // add contents to target buffer, if given, and calculate also
            // total object lengths together to know when stop. In indefinite
            // case stop when end-of-content tag found.
            temp.Read(aData);

            tempTag = temp.Type();

            if ((tempTag == KBerEndOfContent) ||
                (tempTag == KBerUnknown) ||
                (!(tempTag & parentTag)))
                {
                CleanupStack::PopAndDestroy();  // delete tempBuf;
                return read;                // break
                }

            len += temp.ObjectLen();
            read += temp.ContentLen();

            if (aBuf != 0)
                {
                // Resize buffer, if needed, and append data to it.
                if (aBuf->Length() < read)
                    {
                    // It is impossible to know how long buffer should be,
                    // but add some extra space, so reallocation won't occur
                    // each time.
                    aBuf->ReAllocL(read + (read / 5));
                    ptr = aBuf->Des();
                    }

                temp.Content(tempBuf);
                ptr.Append(*tempBuf);
                }
            }

        CleanupStack::PopAndDestroy();      // delete tempBuf;
        }

    return read;
    }



// -----------------------------------------------------------------------------
// CCrBer::Type
// Get type of the object.
// -----------------------------------------------------------------------------
EXPORT_C TBerTag CCrBer::Type()
    {
	return iType;
    }

// -----------------------------------------------------------------------------
// CCrBer::Value
// Get value of the object. Used in encoding.
// -----------------------------------------------------------------------------
TInt CCrBer::Value()
    {
    return iValue;
    }
// -----------------------------------------------------------------------------
// CCrBer::GetBigInt
// -----------------------------------------------------------------------------
RInteger CCrBer::GetBigInt()
    {
    return iInt;
    }

// -----------------------------------------------------------------------------
// CCrBer::SetValue
// Set value of the object.
// -----------------------------------------------------------------------------
TAny CCrBer::SetValue(TInt aInt)
    {
    iValue = aInt;
    }

// -----------------------------------------------------------------------------
// CCrBer::ValuePtr
// Get valuePtr of the object. (encoding)
// -----------------------------------------------------------------------------
TDesC8* CCrBer::ValuePtr()
    {
    return iValuePtr;
    }

// -----------------------------------------------------------------------------
// CCrBer::LenLen
// Get amount of length bytes.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::LenLen()
    {
    return iLenLen;
    }

// -----------------------------------------------------------------------------
// CCrBer::ObjectBegin
// Return begin of the whole object.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::ObjectBegin()
    {
    return iObjectBegin;
    }

// -----------------------------------------------------------------------------
// CCrBer::ContentBegin
// Return begin of the content.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::ContentBegin()
    {
    return iContentBegin;
    }

// -----------------------------------------------------------------------------
// CCrBer::ObjectLen
// Get length of the whole object.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::ObjectLen()
    {
	return iObjectLen;
	}

// -----------------------------------------------------------------------------
// CCrBer::ContentLen
// Get length of the content.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::ContentLen()
    {
    return iContentLen;
    }

// -----------------------------------------------------------------------------
// CCrBer::Indefinite
// Returns true if this object is indefinite length.
// -----------------------------------------------------------------------------
EXPORT_C TBool CCrBer::Indefinite()
    {
    return iIndefinite;
    }

// -----------------------------------------------------------------------------
// CCrBer::Data
// Return pointer to data object.
// -----------------------------------------------------------------------------
EXPORT_C CCrData* CCrBer::Data()
    {
    return iData;
    }

// -----------------------------------------------------------------------------
// CCrBer::Object
// Return whole BER object with tag and stuff. For implementation
// reasons ObjectL returns only max 255 bytes of data.
// -----------------------------------------------------------------------------

EXPORT_C TInt CCrBer::Object(HBufC8* aBuf)
    {
    return BufferL(aBuf, iData, iObjectBegin, iObjectLen);
    }

// -----------------------------------------------------------------------------
// CCrBer::Object
// Return whole BER object with tag and stuff. For implementation
// reasons ObjectL returns only max 255 bytes of data.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::ObjectL(HBufC* aBuf)
    {
    TUint8 len = 255;


    if (iObjectLen < 255)
        {
        len = (TUint8)iObjectLen;
        }
	
    return BufferL(aBuf, iData, iObjectBegin, len);
    }

// -----------------------------------------------------------------------------
// CCrBer::Content
// Return content of this object. For implementation reasons
// ContentL returns only max 255 bytes of data.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::Content(HBufC8* aBuf)
    {
    return BufferL(aBuf, iData, iContentBegin, iContentLen);
    }

// -----------------------------------------------------------------------------
// CCrBer::ContentL
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::ContentL(HBufC* aBuf)
    {
    TUint8 len = 255;

    if (iContentLen < 255)
        {
        len = (TUint8)iContentLen;
        }

    return BufferL(aBuf, iData, iContentBegin, len);
    }

// -----------------------------------------------------------------------------
// CCrBer::BufferL
// Read aAmount of data starting from begin to the buffer.
// Return amount of data read. For implementation reasons
// BufferL can be used only to read max 256 bytes of data.
// -----------------------------------------------------------------------------
EXPORT_C TInt CCrBer::BufferL(
    HBufC8*   aBuf,
    CCrData*  aData,
    TUint     aBegin  /* = 0 */,
    TUint     aAmount /* = KReadBufMax */)
    {
    TInt pos = 0;
    TInt begin = aBegin;
    TInt amount = aAmount;
    TInt read = 0;

    if ((aBuf == 0) || (aData == 0))
        {
        // Don't bother to continue.
        return read;
        }

    // Store current position,
    if ((aData->Seek(ESeekCurrent, pos)) != KErrNone)
        {
        // Don't bother to continue.
        return read;
        }

    // Set data pointer to wanted position.
    if (aData->Seek(ESeekStart, begin) == KErrNone)
        {
        // Resize buffer, if needed, and read data.
        if (aBuf->Length() < amount)
            {
            aBuf->ReAllocL(amount);
            }

        TPtr8 ptr = aBuf->Des();

        if (aData->Read(ptr, amount) == KErrNone)
            {
            read = aBuf->Length();
            }
        }

    // Put data pointer back to previous position.
    aData->Seek(ESeekStart, pos);

    return read;
    }

EXPORT_C TInt CCrBer::BufferL(
    HBufC*   aBuf,
    CCrData* aData,
    TUint    aBegin  /* = 0 */,
    TUint8   aAmount /* = 255 */)
    {
    TInt      index = 0;
    TInt      len = 0;
    TInt      amount = NULL;
    TBuf<255> buf;
    HBufC8*   heapBuf = NULL;

    heapBuf = HBufC8::NewLC(255);

    amount = BufferL(heapBuf, aData, aBegin, aAmount);

    len = heapBuf->Length();

    for (index = 0; index < len; index++)
        {
        buf.Append((*heapBuf)[index]);
        }

    *aBuf = buf;

    CleanupStack::PopAndDestroy();      // delete heapBuf;
    // heapBuf = NULL;

    return amount;
    }


// -----------------------------------------------------------------------------
// CCrBer::Level
// Return nesting level of this object.
// -----------------------------------------------------------------------------
EXPORT_C TUint CCrBer::Level()
    {
    return iLevel;
    }

// -----------------------------------------------------------------------------
// CCrBer::SetLevel
// Set nesting level of this object.
// -----------------------------------------------------------------------------
EXPORT_C TUint CCrBer::SetLevel(TUint aLevel)
    {
    iLevel = aLevel;

    return iLevel;
    }

// -----------------------------------------------------------------------------
// CCrBer::AddToContentLen
// Add given integer to content length of this object.
// -----------------------------------------------------------------------------
EXPORT_C TAny CCrBer::AddToContentLen(TInt iLen)
    {
    iContentLen += iLen;
    }

// -----------------------------------------------------------------------------
// CCrBer::SetObjectLen
// Calculate object length from tag, length's length, and
// content's length. Used to 'close' indefinite objects, meaning
// that their end-of-contents tag is finally found, so their
// length can be calculated.
// -----------------------------------------------------------------------------
EXPORT_C TAny CCrBer::SetObjectLen()
    {
    // Objects length is tag len (always 1) + length byte
    // amount + content length.
    iObjectLen = 1 + iLenLen + iContentLen;

    // If object was of indefinite length, there are
    // two additional end-of-contents bytes at the end.
    if (iIndefinite)
        {
        iObjectLen += 2;
        }
    }

// -----------------------------------------------------------------------------
// CCrBer::SetObjLenWithOutContent
// Parameters:     Content length.
// -----------------------------------------------------------------------------
TAny CCrBer::SetObjLenWithOutContent(TUint aContentLen)
    {
    iObjectLen  = KBerShortLen;             // Tag + len
    if (aContentLen >= KBerLongLengthBit)
        {
        while (aContentLen > 0)                    
            {
            aContentLen >>= 8;              // Next byte
            iObjectLen++;                 
            }
        }
    }

// -----------------------------------------------------------------------------
// Get content functions.
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// CCrBer::GetBooleanL
// Returns value of Boolean object.
// -----------------------------------------------------------------------------
EXPORT_C TBool CCrBer::GetBooleanL()
    {		
    TInt err = KErrNone;
    TASN1DecBoolean dec;                                // ASN1 lib (Symbian)
    TInt pos    = NULL;
    TBool ret   = EFalse;

    HBufC8* buf = HBufC8::NewLC(iObjectLen);            // buffer to object

    TPtr8 ptr   = buf->Des();
   
    err = iData->Read(iObjectBegin,ptr,iObjectLen);     // Read object

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos); 	        // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }

    CleanupStack::PopAndDestroy();                      // delete buf;
 
    return ret;
    }	

// -----------------------------------------------------------------------------
// CCrBer::GetIntegerL
// Returns value of Integer object.
// -----------------------------------------------------------------------------		
EXPORT_C TInt CCrBer::GetIntegerL()
    {
    TInt err = KErrNone;
    TASN1DecInteger dec;                                // ASN1 lib (Symbian)
    TInt pos    = NULL;
    TInt ret    = NULL;

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object

    TPtr8 ptr   = buf->Des();
   
    err = iData->Read(iObjectBegin,ptr,iObjectLen);     // Read object

    if (err == KErrNone)
        {
        ret = dec.DecodeDERShortL(ptr, pos);        	// decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }

    CleanupStack::PopAndDestroy();                      // delete buf;

    return ret;
    }

// -----------------------------------------------------------------------------
// CCrBer::GetIntegerL
// Returns value of Long Integer object.
// -----------------------------------------------------------------------------		
EXPORT_C RInteger CCrBer::GetLongIntegerL()
    {	
    TInt err    = KErrNone;
    TInt pos    = NULL;
    TASN1DecInteger dec;                                // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object

    TPtr8 ptr   = buf->Des();
    RInteger value;

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);

    if (err == KErrNone)
        {
        value = dec.DecodeDERLongL(ptr, pos);           // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
    
    CleanupStack::PopAndDestroy();                      // delete buf;

    return value;
    }
  
// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetOidL
// Returns value of object identifier.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetOidL()
    {	
    TInt err    = KErrNone;
    TInt pos    = NULL;
    HBufC* ret  = NULL;
    TASN1DecObjectIdentifier dec;                       // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);            // buffer to object

    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }

    CleanupStack::PopAndDestroy();                      // delete buf;

    return ret;
    }

// -----------------------------------------------------------------------------
// HBufC8* CCrBer::GetOctetStringL
// Returns value of octet string.
// -----------------------------------------------------------------------------
EXPORT_C HBufC8* CCrBer::GetOctetStringL()
    {	
    TInt pos = NULL;
    HBufC8* ret = NULL;
    TInt err = KErrNone;
    TASN1DecOctetString dec;                            // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object

    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy(buf);                  // delete buf;
        User::Leave(err);
        }

    CleanupStack::PopAndDestroy(buf);                      // delete buf;

    return ret;
    }

// -----------------------------------------------------------------------------
// HBufC8* CCrBer::GetOctetStringL
// Returns value of octet string.
// -----------------------------------------------------------------------------
EXPORT_C TAny CCrBer::GetOctetStringL(CCrData& Trg)
    {	
    TUint pos = iContentBegin;
    TUint end = iContentBegin + iContentLen;
    TInt err = KErrNone;
    TInt len = KBufSize;
    HBufC8* buf = HBufC8::NewL(KBufSize);              // buffer to object
    CleanupStack::PushL(buf);

    TPtr8 ptr   = buf->Des();
    // Read object to buf
    while (pos < end)
        {
        len = end - pos;

        if (len > KBufSize)
            {
            len = KBufSize;
            }

        err = iData->Read(pos, ptr, len);    
        
        if (err == KErrNone)
            {
            Trg.Write(ptr);
            }
        if (err < KErrNone)
            {        
            CleanupStack::PopAndDestroy();
            // buf = NULL;
            User::Leave(err);
            }
        pos += KBufSize;
        }
    CleanupStack::PopAndDestroy(); // buf
    }

// -----------------------------------------------------------------------------
// HBufC8* CCrBer::GetContentStringLC
// Note buf is left to CleanupStack.
// Returns value of content string.
// -----------------------------------------------------------------------------
EXPORT_C HBufC8* CCrBer::GetContentStringLC()
    {	       
    HBufC8* buf = HBufC8::NewL(iContentLen);             // buffer to Content
    CleanupStack::PushL(buf);

    TPtr8 ptr   = buf->Des();

    // Read object to buf
    iData->Read(iContentBegin, ptr, iContentLen);    

    return buf;
    }

// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetIA5StringL
// Returns value of IA5 string object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetIA5StringL()
    {		
    TInt err    = KErrNone;
    TInt pos    = NULL;
    HBufC* ret  = NULL;
    TASN1DecIA5String dec;                              // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
     
    CleanupStack::PopAndDestroy();                      // delete buf;
    
    return ret;
    }

// -----------------------------------------------------------------------------
// TTime CCrBer::GetUTCTimeL
// Returns value of UTC time object.
// -----------------------------------------------------------------------------
EXPORT_C TTime CCrBer::GetUTCTimeL()
    {
    TInt err = KErrNone;
    TInt pos = NULL;
    TTime ret = TTime(0);
    TASN1DecUTCTime dec;                                // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }  

    CleanupStack::PopAndDestroy();                      // delete buf;

    return ret;
    }



// -----------------------------------------------------------------------------
// TTime CCrBer::GetGeneralizedTimeL
// Returns value of generalised time object.
// -----------------------------------------------------------------------------
EXPORT_C TTime CCrBer::GetGeneralizedTimeL()
    {
    TInt err = KErrNone;
    TInt pos = NULL;
    TTime ret = TTime(0);
    TASN1DecGeneralizedTime dec;                        // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);            // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }  

    CleanupStack::PopAndDestroy();                      // delete buf;

    return ret;
    }

// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetPrintStringL
// Returns value of printable string object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetPrintStringL()
    {		
    HBufC* ret = NULL;
    TInt err = KErrNone;
    TInt pos = NULL;
    TASN1DecPrintableString dec;                        // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
     
    CleanupStack::PopAndDestroy();                      // delete buf;

    return ret;
    }

// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetTeletextStringL
// Returns value of teletext string object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetTeletextStringL()
    {																			
    TInt err = KErrNone;
    TInt pos = NULL;
    HBufC* ret = NULL;
    TASN1DecTeletexString dec;                          // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
    
    CleanupStack::PopAndDestroy();                      // delete buf;
    
    return ret;
    }



// -----------------------------------------------------------------------------
// HBufC8* CCrBer::GetSequence
// Returns value of segunce object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC8* CCrBer::GetSequenceL()
    {
    TInt err = KErrNone;
    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(ContentBegin(),ptr,ContentLen());
	
    if (err < KErrNone)
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        // buf = NULL;
        User::Leave(err);
        }
    CleanupStack::PopAndDestroy();                      // delete buf;
    // buf = NULL;

    return ptr.AllocL();
    }

// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetVideoString
// Returns value of video string object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetVideoStringL()
    {
    TInt err = KErrNone;
    HBufC* ret = NULL;
    TInt pos   = NULL;
    TASN1DecVideotexString dec;                         // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
    
    CleanupStack::PopAndDestroy();                      // delete buf;

    return ret;
    }

// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetGeneralString
// Returns value of general string object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetGeneralStringL()
    {
    TInt err    = KErrNone;
    TInt pos    = NULL;
    HBufC* ret  = NULL;
    TASN1DecGeneralString dec;                          // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
    
    CleanupStack::PopAndDestroy();                      // delete buf;

    return ret;
    }

// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetVisibleStringL
// Returns value of visible string object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetVisibleStringL()
    {
    TInt err    = KErrNone;
    HBufC* ret  = NULL;
    TInt pos    = NULL;
    TASN1DecVisibleString dec;                          // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
    
    CleanupStack::PopAndDestroy();                      // delete buf;

    return ret;
    }

// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetGraphicsStringL
// Returns value of graphical string object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetGraphicsStringL()
    {
    TInt err    = KErrNone;
    HBufC* ret  = NULL;
    TInt pos    = NULL;
    TASN1DecGraphicString dec;                          // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
   
    CleanupStack::PopAndDestroy();                      // delete buf;
    
    return ret;
    }



// -----------------------------------------------------------------------------
// HBufC* CCrBer::GetNumericStringL
// Returns value of numeric string object.
// -----------------------------------------------------------------------------
EXPORT_C HBufC* CCrBer::GetNumericStringL()
    {
    TInt err    = KErrNone;
    HBufC* ret  = NULL;
    TInt pos    = NULL;
    TASN1DecNumericString dec;                          // ASN1 lib (Symbian)

    HBufC8* buf = HBufC8::NewLC(iObjectLen);             // buffer to object
    TPtr8 ptr   = buf->Des();

    // Read object to buf
    err = iData->Read(iObjectBegin,ptr,iObjectLen);    

    if (err == KErrNone)
        {
        ret = dec.DecodeDERL(ptr, pos);                 // decode object
        }
    else
        {        
        CleanupStack::PopAndDestroy();                  // delete buf;
        User::Leave(err);
        }
   
    CleanupStack::PopAndDestroy();                      // delete buf;
    
    return ret;
    }

// -----------------------------------------------------------------------------
//  Encoding
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// CCrBer::CreateBool
// Paremeters:     Value of the boolean object. True or False.
// -----------------------------------------------------------------------------
TAny CCrBer::CreateBool(TBool aBool)
    {
    iType       = KBerBoolean;
    iObjectLen  = KBerBooleanLen;           // Boolean object len is always 3
    iValue      = aBool; 
    }                                       

// -----------------------------------------------------------------------------
// CCrBer::CreateInt
// Paremeters:     Value of the object (positive, null or negative)
//                 e.g. 234 or 0xFFF or -45676.
// -----------------------------------------------------------------------------
TAny CCrBer::CreateInt(TInt aInt)
    {
    iType       = KBerInteger;
    iValue      = aInt; 

    // Find out object len. Tag + len + value.
    if (aInt == 0 || (aInt > (-0x81) &&  aInt < 0x80 ))
        iObjectLen  = 0x03;                 
    
    else if (aInt > (-0x8001) && aInt < 0x8000)                            
        iObjectLen  = 0x04;

    else if (aInt > (-0x800001) && aInt < 0x800000)
        iObjectLen  = 0x05;

    else
        iObjectLen  = 0x06;
    }

// -----------------------------------------------------------------------------
// CCrBer::CreateInt
// Paremeters:     Value of the object (positive, null or negative)
//                 e.g. 234 or 0xFFF or -45676.
// -----------------------------------------------------------------------------
TAny CCrBer::CreateLongInt(RInteger& aData)
    {
    TInt len    = aData.ByteCount();
    iType       = KBerInteger;
    iValue      = NULL;
    iInt        = RInteger::NewL(aData);

    iObjectLen  = KBerShortLen + len;       // Tag + len(lenlen) + string 

    if (len >= KBerLongLengthBit)
        {         
        while (len > NULL)                  // add number of lenbytes 
            {
            len >>= KOctetWidth;            // Next byte
            iObjectLen++;   
            }
        }
    }

// -----------------------------------------------------------------------------
// CCrBer::CreateNull
// -----------------------------------------------------------------------------
TAny CCrBer::CreateNull()
    {
    iType       = KBerNull;                 // Tag
    iObjectLen  = KBerNullLen;              // 05 00
    }

// -----------------------------------------------------------------------------
// CCrBer::CreateOId
// Paremeters:     Pointer to string. e.g.(1.2.43.4335.242)
// -----------------------------------------------------------------------------
TAny CCrBer::CreateOIdL(TDesC8* aString)
    {
    CCrBerSet* set = CCrBerSet::NewLC(1);
    TInt len    = set->AppendObjectIdL(*aString, ETrue);// ask Oid content len
    iType       = KBerOid;
    iValuePtr   = aString;
        
    iObjectLen  = (len > NULL) ? KBerShortLen + len : 0; // tag + len + content
   
    CleanupStack::PopAndDestroy();  // delete set;
    // set = NULL;    
    }



// -----------------------------------------------------------------------------
// CCrBer::CreateString
// Paremeters:     Type of object and pointer to string.
// -----------------------------------------------------------------------------
TAny CCrBer::CreateString(TBerTag aTag, TDesC8* aString)
    {
    TInt len    = aString->Length();
    iType       = aTag;
    iValuePtr   = aString;  
    iObjectLen  = KBerShortLen + len;       // Tag + len(lenlen) + string 

    if (len >= KBerLongLengthBit)
        {         
        while (len > NULL)                  // add number of lenbytes 
            {
            len >>= KOctetWidth;            // Next byte
            iObjectLen++;   
            }
        }
    }

// -----------------------------------------------------------------------------
// CCrBer::CreateString
// -----------------------------------------------------------------------------
TAny CCrBer::CreateString(TBerTag aTag, CCrData* aData)
    {
    TInt len    =  0;
    aData->Size(len);
    iType       = aTag;
    iData   = aData;  
    iObjectLen  = KBerShortLen + len;       // Tag + len(lenlen) + string 

    if (len >= KBerLongLengthBit)
        {         
        while (len > NULL)                  // add number of lenbytes 
            {
            len >>= KOctetWidth;            // Next byte
            iObjectLen++;   
            }
        }
    }

// -----------------------------------------------------------------------------
// CCrBer::CreateStart
// Paremeters:     First parameter is tag type (e.g. seq). Second param is
//                 True if definite length is wanted.
//                 False if indefinite (xx 80) .
// -----------------------------------------------------------------------------
TAny CCrBer::CreateStart(TBerTag aTag, TBool aDefinite)
    {
    iType = aTag;

    // Definite object length = 0 (set rigth length later).
    // Indefinite object length is always 4 (Tag + 80 + 00 + 00)
    if (!aDefinite)
        {
        iObjectLen = KBerIndefiniteLen;
        }
    }                                                   
                                            
// -----------------------------------------------------------------------------
// CCrBer::CreateEnd
// -----------------------------------------------------------------------------
TAny CCrBer::CreateEnd()
    {
    iType   = KBerEndOfContent;                   // =0x00
    iValue  = KBerEndOfContent;
    }                                       

// -----------------------------------------------------------------------------
// CCrBer::CreateBEREncodedObject
// This fuction can be used to create a BER object
// from buffer, which already contains a full BER
// encoded object.
// Paremeters:     Buffer containing BER encoded object.
// -----------------------------------------------------------------------------
TAny CCrBer::CreateBEREncodedObject(TDesC8* aBuffer)
    {
    iType      = KBerEncodedObject;
    iValuePtr  = aBuffer;  
    iObjectLen = aBuffer->Length();
    }

// ========================== OTHER EXPORTED FUNCTIONS =========================
                                                                                
// ---------------------------------------------------------
// E32Dll
// DLL entry point
// ---------------------------------------------------------
//
#ifndef EKA2
GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
    {
    return KErrNone;
    }
#endif