sl@0: /* sl@0: * Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Define methods for asn1-encoding base class sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include "base128enc.h" sl@0: #include "panic.h" sl@0: sl@0: #include sl@0: sl@0: const TUint KMaxLowNumberFormTag = 30; sl@0: const TUint KMaxShortFormLength = 127; sl@0: sl@0: sl@0: EXPORT_C CASN1EncBase::CASN1EncBase(const TTagType aType, const TASN1Class aClass) sl@0: : iType(aType), iClass(aClass) sl@0: { sl@0: CalculateTagLengthDER(); sl@0: } sl@0: sl@0: sl@0: EXPORT_C CASN1EncBase::~CASN1EncBase() sl@0: { sl@0: } sl@0: sl@0: sl@0: EXPORT_C void CASN1EncBase::ConstructL() sl@0: { sl@0: ContentsLengthChanged(); sl@0: } sl@0: sl@0: sl@0: void CASN1EncBase::ContentsLengthChanged() sl@0: { sl@0: CalculateContentsLengthDER(); sl@0: CalculateLengthLengthDER(); sl@0: sl@0: if (iParent) sl@0: { sl@0: iParent->ContentsLengthChanged(); sl@0: } sl@0: } sl@0: sl@0: sl@0: // Set tagging scheme/tag/class sl@0: EXPORT_C void CASN1EncBase::SetTag(const TTagType aType, const TASN1Class aClass) sl@0: { sl@0: iType = aType; sl@0: iClass = aClass; sl@0: sl@0: CalculateTagLengthDER(); sl@0: } sl@0: sl@0: sl@0: // Gives total number of octets in the DER encoding of this object sl@0: EXPORT_C TUint CASN1EncBase::LengthDER() const sl@0: { sl@0: return iTagLengthDER + iLengthLengthDER + iContentsLengthDER; sl@0: } sl@0: sl@0: sl@0: // Writes entire DER encoding of this object into the given buffer sl@0: EXPORT_C void CASN1EncBase::WriteDERL(TDes8& aBuf, TUint& aPos) const sl@0: { sl@0: __ASSERT_ALWAYS(aBuf.Length() - STATIC_CAST(TInt, aPos) >= STATIC_CAST(TInt, LengthDER()), sl@0: Panic(KErrDescriptorTooShort)); sl@0: sl@0: WriteHelperL(aBuf, aPos, iTagLengthDER, &CASN1EncBase::WriteTagDERL); sl@0: WriteHelperL(aBuf, aPos, iLengthLengthDER, &CASN1EncBase::WriteLengthDER); sl@0: WriteHelperL(aBuf, aPos, iContentsLengthDER, &CASN1EncBase::WriteContentsDERL); sl@0: } sl@0: sl@0: sl@0: // Internal helper method, used for efficiency sl@0: void CASN1EncBase::WriteHelperL(TDes8& aBuf, TUint& aPos, const TUint aLength, sl@0: WriteFunc aWriteFunc) const sl@0: { sl@0: if (aLength) sl@0: { sl@0: // Get the middle bit of buffer we should be using sl@0: TPtr8 ptr(&aBuf[aPos], aLength, aLength); sl@0: sl@0: // Call the function to actually write the data sl@0: (this->*aWriteFunc)(ptr); sl@0: sl@0: aPos += aLength; sl@0: } sl@0: } sl@0: sl@0: sl@0: // Give number of octets in tag section sl@0: void CASN1EncBase::CalculateTagLengthDER() sl@0: { sl@0: if (iType <= KMaxLowNumberFormTag) sl@0: { sl@0: // Low tag number form sl@0: iTagLengthDER = 1; sl@0: } sl@0: else sl@0: { sl@0: // High tag number form sl@0: TASN1EncBase128DER encoder(iType); sl@0: iTagLengthDER = encoder.LengthDER() + 1; sl@0: } sl@0: } sl@0: sl@0: sl@0: // Give number of octets in length section sl@0: // Only called after contents length is worked out sl@0: void CASN1EncBase::CalculateLengthLengthDER() sl@0: { sl@0: iLengthLengthDER = 1; sl@0: if (iContentsLengthDER > KMaxShortFormLength) sl@0: { sl@0: // Long form - need number of octets in base256 representation sl@0: // of length, plus 1. sl@0: sl@0: TUint working = iContentsLengthDER; sl@0: do sl@0: { sl@0: ++iLengthLengthDER; sl@0: } sl@0: while (working >>= 8); sl@0: } sl@0: } sl@0: sl@0: sl@0: // Writes the tag section into the given buffer sl@0: void CASN1EncBase::WriteTagDERL(TDes8& aBuf) const sl@0: { sl@0: // Write class - bits 7-8 sl@0: aBuf[0] = STATIC_CAST(TUint8, iClass << 6); sl@0: sl@0: // Write constructed/primitive flag in bit 6 sl@0: if (IsConstructed()) sl@0: { sl@0: aBuf[0] |= 0x20; sl@0: } sl@0: sl@0: // Write length sl@0: if (iType <= KMaxLowNumberFormTag) sl@0: { sl@0: aBuf[0] |= iType; sl@0: } sl@0: else sl@0: { sl@0: // First byte signals more to come sl@0: aBuf[0] |= 0x1F; sl@0: sl@0: // The rest we delegate sl@0: TASN1EncBase128DER encoder(iType); sl@0: TUint offset = 1; sl@0: encoder.WriteDERL(aBuf, offset); sl@0: } sl@0: } sl@0: sl@0: sl@0: // Writes the length section into the given buffer sl@0: void CASN1EncBase::WriteLengthDER(TDes8& aBuf) const sl@0: { sl@0: if (iContentsLengthDER > KMaxShortFormLength) sl@0: { sl@0: // First byte is the number of other bytes, with top bit also set sl@0: TUint octets = iLengthLengthDER - 1; sl@0: sl@0: // Cast takes 8 least sig bits sl@0: aBuf[0] = STATIC_CAST(TUint8, octets); sl@0: aBuf[0] |= 0x80; sl@0: sl@0: // Other bytes are base 256 representation of length, most significant first sl@0: TUint working = iContentsLengthDER; sl@0: do sl@0: { sl@0: // Cast to TUint8 takes 8 least sig bits sl@0: aBuf[octets] = STATIC_CAST(TUint8, working); sl@0: working >>= 8; sl@0: } sl@0: while (--octets); sl@0: } sl@0: else sl@0: { sl@0: // Short form, nice and easy - take least sig 8 bits with a cast sl@0: aBuf[0] = STATIC_CAST(TUint8, iContentsLengthDER); sl@0: } sl@0: } sl@0: sl@0: sl@0: // Sets the parent (can only do this once) sl@0: void CASN1EncBase::SetParent(CASN1EncBase* aParent) sl@0: { sl@0: __ASSERT_ALWAYS(iParent == 0, Panic(KErrAlreadyHasParent)); sl@0: iParent = aParent; sl@0: }